From 4771ae9fb830eae58ea4dc8e92056eabe7f98c59 Mon Sep 17 00:00:00 2001 From: Konstantinos Chatzilygeroudis Date: Wed, 17 Feb 2021 17:40:44 +0200 Subject: [PATCH 001/161] [WindowLessApps]: add release option to contexts [egl,cgl,glx for linux] --- src/Magnum/Platform/WindowlessCglApplication.cpp | 8 ++++++++ src/Magnum/Platform/WindowlessCglApplication.h | 8 ++++++++ src/Magnum/Platform/WindowlessEglApplication.cpp | 10 +++++++++- src/Magnum/Platform/WindowlessEglApplication.h | 8 ++++++++ src/Magnum/Platform/WindowlessGlxApplication.cpp | 8 ++++++++ src/Magnum/Platform/WindowlessGlxApplication.h | 8 ++++++++ 6 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Platform/WindowlessCglApplication.cpp b/src/Magnum/Platform/WindowlessCglApplication.cpp index 7afb30659..c7e5b4819 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.cpp +++ b/src/Magnum/Platform/WindowlessCglApplication.cpp @@ -97,6 +97,14 @@ bool WindowlessCglContext::makeCurrent() { return false; } +bool WindowlessCglContext::release() { + if(CGLSetCurrentContext(0) == kCGLNoError) + return true; + + Error() << "Platform::WindowlessCglContext::release(): cannot release current context"; + return false; +} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments): WindowlessCglApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index a32902018..a328c1081 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -126,6 +126,14 @@ class WindowlessCglContext { */ bool makeCurrent(); + /** + * @brief Release current context + * + * Prints error message and returns @cpp false @ce on failure, + * otherwise returns @cpp true @ce. + */ + bool release(); + /** * @brief Underlying OpenGL context * @m_since{2020,06} diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index f75dcf4c0..668a5ef3c 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -503,7 +503,15 @@ bool WindowlessEglContext::makeCurrent() { return true; #endif - Error() << "Platform::WindowlessEglApplication::tryCreateContext(): cannot make context current:" << Implementation::eglErrorString(eglGetError()); + Error() << "Platform::WindowlessEglApplication::makeCurrent(): cannot make context current:" << Implementation::eglErrorString(eglGetError()); + return false; +} + +bool WindowlessEglContext::release() { + if(eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) + return true; + + Error() << "Platform::WindowlessEglApplication::release(): cannot release current context:" << Implementation::eglErrorString(eglGetError()); return false; } diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index 04091b0ef..7ac1cb0ca 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -127,6 +127,14 @@ class WindowlessEglContext { */ bool makeCurrent(); + /** + * @brief Release current context + * + * Prints error message and returns @cpp false @ce on failure, + * otherwise returns @cpp true @ce. + */ + bool release(); + /** * @brief Underlying OpenGL context * @m_since{2020,06} diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index a885adb84..4a6d1a249 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -255,6 +255,14 @@ bool WindowlessGlxContext::makeCurrent() { return false; } +bool WindowlessGlxContext::release() { + if(glXMakeContextCurrent(_display, 0, 0, nullptr)) + return true; + + Error() << "Platform::WindowlessGlxContext::release(): cannot release current context"; + return false; +} + WindowlessGlxContext::Configuration::Configuration(): #ifndef MAGNUM_TARGET_GLES _flags{Flag::ForwardCompatible} diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 0eddcddf8..f58685d55 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -146,6 +146,14 @@ class WindowlessGlxContext { */ bool makeCurrent(); + /** + * @brief Release current context + * + * Prints error message and returns @cpp false @ce on failure, + * otherwise returns @cpp true @ce. + */ + bool release(); + /** * @brief Underlying OpenGL context * @m_since{2020,06} From b4d7c84ee2b9720c93e7e2650e9f5e9ae9e65b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 17 Feb 2021 17:37:05 +0100 Subject: [PATCH 002/161] Platform: fix a crash in GlfwApplication::setCursor() on GLFW 3.4. There's four more new cursors and the _cursors array was too small. At first I got confused because I thought the assertion on top is done against the CursorMap, which didn't contain the Hidden cursors. So to avoid confusing myself again in the future, I moved the assert after the special cases and made both arrays the same size since it doesn't make sense to have always-empty fields in there. Similar change is done in Sdl2Application, and an assert is added to avoid a nondescript crash if the window is not created yet. --- doc/changelog.dox | 2 ++ src/Magnum/Platform/GlfwApplication.cpp | 7 ++++++- src/Magnum/Platform/GlfwApplication.h | 13 +++++++++++-- src/Magnum/Platform/Sdl2Application.cpp | 8 +++++++- src/Magnum/Platform/Sdl2Application.h | 5 +++-- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index ad9f3c3a8..0128bf6a3 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -308,6 +308,8 @@ See also: - Fixed canvas size setup in @ref Platform::EmscriptenApplication to be the same in the @ref Platform::EmscriptenApplication::Configuration::WindowFlag::Contextless "Contextless" case as for a WebGL-enabled context +- Fixed a crash in @ref Platform::GlfwApplication::setCursor() on the + upcoming GLFW 3.4 - @ref SceneGraph::BasicMatrixTransformation2D, @ref SceneGraph::BasicMatrixTransformation3D, @ref SceneGraph::BasicRigidMatrixTransformation2D and diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 6d5eae4aa..1952ed6d9 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -797,7 +797,7 @@ constexpr Int CursorMap[] { } void GlfwApplication::setCursor(Cursor cursor) { - CORRADE_INTERNAL_ASSERT(UnsignedInt(cursor) < Containers::arraySize(_cursors)); + CORRADE_ASSERT(_window, "Platform::GlfwApplication::setCursor(): no window opened", ); _cursor = cursor; @@ -811,6 +811,11 @@ void GlfwApplication::setCursor(Cursor cursor) { glfwSetInputMode(_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } + /* The second condition could be a static assert but it doesn't let me + because "this pointer only accessible in a constexpr function". Thanks + for nothing, C++. */ + CORRADE_INTERNAL_ASSERT(UnsignedInt(cursor) < Containers::arraySize(_cursors) && Containers::arraySize(_cursors) == Containers::arraySize(CursorMap)); + if(!_cursors[UnsignedInt(cursor)]) _cursors[UnsignedInt(cursor)] = glfwCreateStandardCursor(CursorMap[UnsignedInt(cursor)]); diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index c581824a4..e32d56f40 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -624,7 +624,8 @@ class GlfwApplication { * @brief Set cursor type * @m_since{2020,06} * - * Default is @ref Cursor::Arrow. + * Expects that a window is already created. Default is + * @ref Cursor::Arrow. */ void setCursor(Cursor cursor); @@ -735,7 +736,15 @@ class GlfwApplication { void setupCallbacks(); - GLFWcursor* _cursors[8]{}; + /* Corresponds to size of the Cursor enum, the two Hidden cursors are + handled differently */ + GLFWcursor* _cursors[ + #ifndef GLFW_RESIZE_NWSE_CURSOR + 6 + #else + 10 + #endif + ]{}; Cursor _cursor = Cursor::Arrow; /* These are saved from command-line arguments */ diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index f1f99cc16..aed91cacb 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -1052,7 +1052,7 @@ constexpr const char* CursorMap[] { void Sdl2Application::setCursor(Cursor cursor) { #ifndef CORRADE_TARGET_EMSCRIPTEN - CORRADE_INTERNAL_ASSERT(UnsignedInt(cursor) < Containers::arraySize(_cursors)); + CORRADE_ASSERT(_window, "Platform::Sdl2Application::setCursor(): no window opened", ); if(cursor == Cursor::Hidden) { SDL_ShowCursor(SDL_DISABLE); @@ -1069,11 +1069,17 @@ void Sdl2Application::setCursor(Cursor cursor) { SDL_SetRelativeMouseMode(SDL_FALSE); } + /* The second condition could be a static assert but it doesn't let me + because "this pointer only accessible in a constexpr function". Thanks + for nothing, C++. */ + CORRADE_INTERNAL_ASSERT(UnsignedInt(cursor) < Containers::arraySize(_cursors) && Containers::arraySize(_cursors) == Containers::arraySize(CursorMap)); + if(!_cursors[UnsignedInt(cursor)]) _cursors[UnsignedInt(cursor)] = SDL_CreateSystemCursor(CursorMap[UnsignedInt(cursor)]); SDL_SetCursor(_cursors[UnsignedInt(cursor)]); #else + CORRADE_ASSERT(_surface, "Platform::Sdl2Application::setCursor(): no window opened", ); _cursor = cursor; CORRADE_INTERNAL_ASSERT(UnsignedInt(cursor) < Containers::arraySize(CursorMap)); #pragma GCC diagnostic push diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 3cbd57b26..20c619c57 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -968,7 +968,8 @@ class Sdl2Application { * @brief Set cursor type * @m_since{2020,06} * - * Default is @ref Cursor::Arrow. + * Expects that a window is already created. Default is + * @ref Cursor::Arrow. */ void setCursor(Cursor cursor); @@ -1184,7 +1185,7 @@ class Sdl2Application { CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) #ifndef CORRADE_TARGET_EMSCRIPTEN - SDL_Cursor* _cursors[14]{}; + SDL_Cursor* _cursors[12]{}; #else Cursor _cursor; #endif From 27074d97fe1432c2d975240a89ce13a1a7d446b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 20 Feb 2021 19:16:08 +0100 Subject: [PATCH 003/161] Platform: added WindowlessIosContext::glContext() for consistency. All other classes have it, so why not here as well. --- doc/changelog.dox | 2 ++ src/Magnum/Platform/WindowlessIosApplication.h | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/doc/changelog.dox b/doc/changelog.dox index 0128bf6a3..605f9df87 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -217,6 +217,8 @@ See also: @ref Platform::EmscriptenApplication and @ref Platform::Sdl2Application now notify about that in the verbose output (enabled with `?magnum-log=verbose`), previously only autodetected canvas size got printed +- Added @ref Platform::WindowlessIosContext::glContext() for consistency with + other context classes @subsubsection changelog-latest-changes-shaders Shaders library diff --git a/src/Magnum/Platform/WindowlessIosApplication.h b/src/Magnum/Platform/WindowlessIosApplication.h index 18bdc92a0..4b1b14243 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.h +++ b/src/Magnum/Platform/WindowlessIosApplication.h @@ -119,6 +119,16 @@ class WindowlessIosContext { */ bool makeCurrent(); + /** + * @brief Underlying OpenGL context + * @m_since_latest + * + * Use in case you need to call EAGL functionality directly or in order + * to create a shared context. Returns @cpp nullptr @ce in case the + * context was not created yet. + */ + EAGLContext* glContext() { return _context; } + private: EAGLContext* _context{}; }; From 0145342196a9946ced92db33b92bf99906890d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 20 Feb 2021 19:29:10 +0100 Subject: [PATCH 004/161] Platform: add context release also to iOS, WGL and Windows EGL apps. --- src/Magnum/Platform/WindowlessIosApplication.h | 15 ++++++++++++++- src/Magnum/Platform/WindowlessIosApplication.mm | 8 ++++++++ src/Magnum/Platform/WindowlessWglApplication.cpp | 8 ++++++++ src/Magnum/Platform/WindowlessWglApplication.h | 15 ++++++++++++++- .../Platform/WindowlessWindowsEglApplication.cpp | 8 ++++++++ .../Platform/WindowlessWindowsEglApplication.h | 15 ++++++++++++++- 6 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Platform/WindowlessIosApplication.h b/src/Magnum/Platform/WindowlessIosApplication.h index 4b1b14243..2e922fc94 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.h +++ b/src/Magnum/Platform/WindowlessIosApplication.h @@ -115,10 +115,23 @@ class WindowlessIosContext { * @brief Make the context current * * Prints error message and returns @cpp false @ce on failure, - * otherwise returns @cpp true @ce. + * otherwise returns @cpp true @ce. If the context is current on + * another thread, you have to @ref release() it there first --- an + * OpenGL context can't be current in multiple threads at the same + * time. */ bool makeCurrent(); + /** + * @brief Release current context + * @m_since_latest + * + * Releases a context previously made current using @ref makeCurrent(). + * Prints error message and returns @cpp false @ce on failure, + * otherwise returns @cpp true @ce. + */ + bool release(); + /** * @brief Underlying OpenGL context * @m_since_latest diff --git a/src/Magnum/Platform/WindowlessIosApplication.mm b/src/Magnum/Platform/WindowlessIosApplication.mm index 15c7cb9ef..83756aeb8 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.mm +++ b/src/Magnum/Platform/WindowlessIosApplication.mm @@ -74,6 +74,14 @@ bool WindowlessIosContext::makeCurrent() { return false; } +bool WindowlessIosContext::release() { + if([EAGLContext setCurrentContext:nil]) + return true; + + Error() << "Platform::WindowlessIosContext::release(): cannot release current context"; + return false; +} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments): WindowlessIosApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index d4e647eea..e697fb442 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -243,6 +243,14 @@ bool WindowlessWglContext::makeCurrent() { return false; } +bool WindowlessWglContext::release() { + if(wglMakeCurrent(_deviceContext, nullptr)) + return true; + + Error() << "Platform::WindowlessWglContext::release(): cannot release current context:" << GetLastError(); + return false; +} + WindowlessWglContext::Configuration::Configuration(): #ifndef MAGNUM_TARGET_GLES _flags{Flag::ForwardCompatible} diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 819928a29..5deb05a9c 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -130,10 +130,23 @@ class WindowlessWglContext { * @brief Make the context current * * Prints error message and returns @cpp false @ce on failure, - * otherwise returns @cpp true @ce. + * otherwise returns @cpp true @ce. If the context is current on + * another thread, you have to @ref release() it there first --- an + * OpenGL context can't be current in multiple threads at the same + * time. */ bool makeCurrent(); + /** + * @brief Release current context + * @m_since_latest + * + * Releases a context previously made current using @ref makeCurrent(). + * Prints error message and returns @cpp false @ce on failure, + * otherwise returns @cpp true @ce. + */ + bool release(); + /** * @brief Underlying OpenGL context * @m_since{2020,06} diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 7ffbdec5a..685a30892 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -173,6 +173,14 @@ bool WindowlessWindowsEglContext::makeCurrent() { return false; } +bool WindowlessWindowsEglContext::release() { + if(eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) + return true; + + Error() << "Platform::WindowlessWindowsEglApplication::release(): cannot release current context:" << GetLastError(); + return false; +} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments): WindowlessWindowsEglApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index c71f1f8d3..589be9571 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -115,10 +115,23 @@ class WindowlessWindowsEglContext { * @brief Make the context current * * Prints error message and returns @cpp false @ce on failure, - * otherwise returns @cpp true @ce. + * otherwise returns @cpp true @ce. If the context is current on + * another thread, you have to @ref release() it there first --- an + * OpenGL context can't be current in multiple threads at the same + * time. */ bool makeCurrent(); + /** + * @brief Release current context + * @m_since_latest + * + * Releases a context previously made current using @ref makeCurrent(). + * Prints error message and returns @cpp false @ce on failure, + * otherwise returns @cpp true @ce. + */ + bool release(); + /** * @brief Underlying OpenGL context * @m_since{2020,06} From 64433315a1d8d6d8b05cf0cd083a44af67218846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 20 Feb 2021 19:25:15 +0100 Subject: [PATCH 005/161] Doc++, updated credits and changelog. Also retroactively added relevant copyright headers to other apps. --- doc/changelog.dox | 5 +++++ src/Magnum/Platform/AbstractXApplication.cpp | 1 + src/Magnum/Platform/AbstractXApplication.h | 1 + src/Magnum/Platform/EmscriptenApplication.h | 2 +- src/Magnum/Platform/GlfwApplication.cpp | 3 ++- src/Magnum/Platform/GlfwApplication.h | 3 ++- src/Magnum/Platform/WindowlessCglApplication.cpp | 1 + src/Magnum/Platform/WindowlessCglApplication.h | 8 +++++++- src/Magnum/Platform/WindowlessEglApplication.cpp | 1 + src/Magnum/Platform/WindowlessEglApplication.h | 10 ++++++++-- src/Magnum/Platform/WindowlessGlxApplication.cpp | 1 + src/Magnum/Platform/WindowlessGlxApplication.h | 8 +++++++- 12 files changed, 37 insertions(+), 7 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 605f9df87..b3f557da9 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -108,6 +108,11 @@ See also: - It's now possible to have multiple @ref Platform::EmscriptenApplication canvases on a single page (see [mosra/magnum#480](https://github.com/mosra/magnum/pull/480), [mosra/magnum#481](https://github.com/mosra/magnum/pull/481)) +- Added @relativeref{Platform::WindowlessEglContext,release()} as a + counterpart to @relativeref{Platform::WindowlessEglContext,makeCurrent()} + to all @cpp Platform::Windowless*Context @ce classes. Useful for + transferring OpenGL contexts between threads, see also + [mosra/magnum#495](https://github.com/mosra/magnum/pull/495). @subsubsection changelog-latest-new-shaders Shaders library diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index ee5a01742..24b1e06c7 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -3,6 +3,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš + Copyright © 2019, 2020 Konstantinos Chatzilygeroudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index 9589be01f..e2745093f 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -5,6 +5,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš + Copyright © 2019, 2020 Konstantinos Chatzilygeroudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index e9d007083..3c7f2659c 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -5,7 +5,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš - Copyright © 2018, 2019 Jonathan Hale + Copyright © 2018, 2019, 2020 Jonathan Hale Copyright © 2020 Pablo Escobar Permission is hereby granted, free of charge, to any person obtaining a diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 1952ed6d9..3115e49c2 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -3,7 +3,8 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš - Copyright © 2016 Jonathan Hale + Copyright © 2016, 2018 Jonathan Hale + Copyright © 2019 Konstantinos Chatzilygeroudis Copyright © 2019, 2020 Marco Melorio Permission is hereby granted, free of charge, to any person obtaining a diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index e32d56f40..3706d7e5d 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -5,7 +5,8 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš - Copyright © 2016 Jonathan Hale + Copyright © 2016, 2018 Jonathan Hale + Copyright © 2019 Konstantinos Chatzilygeroudis Copyright © 2019, 2020 Marco Melorio Permission is hereby granted, free of charge, to any person obtaining a diff --git a/src/Magnum/Platform/WindowlessCglApplication.cpp b/src/Magnum/Platform/WindowlessCglApplication.cpp index c7e5b4819..9ac9395be 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.cpp +++ b/src/Magnum/Platform/WindowlessCglApplication.cpp @@ -5,6 +5,7 @@ 2020, 2021 Vladimír Vondruš Copyright © 2013 Copyright © 2014 Travis Watkins + Copyright © 2021 Konstantinos Chatzilygeroudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index a328c1081..271e0c70f 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -7,6 +7,7 @@ 2020, 2021 Vladimír Vondruš Copyright © 2013 Copyright © 2014 Travis Watkins + Copyright © 2021 Konstantinos Chatzilygeroudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -122,13 +123,18 @@ class WindowlessCglContext { * @brief Make the context current * * Prints error message and returns @cpp false @ce on failure, - * otherwise returns @cpp true @ce. + * otherwise returns @cpp true @ce. If the context is current on + * another thread, you have to @ref release() it there first --- an + * OpenGL context can't be current in multiple threads at the same + * time. */ bool makeCurrent(); /** * @brief Release current context + * @m_since_latest * + * Releases a context previously made current using @ref makeCurrent(). * Prints error message and returns @cpp false @ce on failure, * otherwise returns @cpp true @ce. */ diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 668a5ef3c..6a6462e47 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -4,6 +4,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš Copyright © 2020, 2021 Erik Wijmans + Copyright © 2021 Konstantinos Chatzilygeroudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index 7ac1cb0ca..b79479d5e 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -5,7 +5,8 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš - Copyright © 2020 Erik Wijmans + Copyright © 2020, 2021 Erik Wijmans + Copyright © 2021 Konstantinos Chatzilygeroudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -123,13 +124,18 @@ class WindowlessEglContext { * @brief Make the context current * * Prints error message and returns @cpp false @ce on failure, - * otherwise returns @cpp true @ce. + * otherwise returns @cpp true @ce. If the context is current on + * another thread, you have to @ref release() it there first --- an + * OpenGL context can't be current in multiple threads at the same + * time. */ bool makeCurrent(); /** * @brief Release current context + * @m_since_latest * + * Releases a context previously made current using @ref makeCurrent(). * Prints error message and returns @cpp false @ce on failure, * otherwise returns @cpp true @ce. */ diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index 4a6d1a249..d744cb2bb 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -3,6 +3,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš + Copyright © 2021 Konstantinos Chatzilygeroudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index f58685d55..68dc2d591 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -5,6 +5,7 @@ Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Vladimír Vondruš + Copyright © 2021 Konstantinos Chatzilygeroudis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -142,13 +143,18 @@ class WindowlessGlxContext { * @brief Make the context current * * Prints error message and returns @cpp false @ce on failure, - * otherwise returns @cpp true @ce. + * otherwise returns @cpp true @ce. If the context is current on + * another thread, you have to @ref release() it there first --- an + * OpenGL context can't be current in multiple threads at the same + * time. */ bool makeCurrent(); /** * @brief Release current context + * @m_since_latest * + * Releases a context previously made current using @ref makeCurrent(). * Prints error message and returns @cpp false @ce on failure, * otherwise returns @cpp true @ce. */ From a3d87b104651164c92ad1a9f01e4397714524117 Mon Sep 17 00:00:00 2001 From: Konstantinos Chatzilygeroudis Date: Wed, 3 Mar 2021 01:28:39 +0200 Subject: [PATCH 006/161] [EGL]: undef more Xlib nonsense --- src/Magnum/Platform/WindowlessEglApplication.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index b79479d5e..91b4a4604 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -40,8 +40,15 @@ #undef Always #undef Bool #undef Complex +#undef Convex #undef None #undef Status +#undef Success +#undef Button1 +#undef Button2 +#undef Button3 +#undef Button4 +#undef Button5 #include #include From 4bbc3c0d1fd30c9b022cb34477f677f2ae45d9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 3 Mar 2021 17:20:58 +0100 Subject: [PATCH 007/161] doc: updated changelog. --- doc/changelog.dox | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/changelog.dox b/doc/changelog.dox index b3f557da9..efb2fb9e8 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -224,6 +224,8 @@ See also: previously only autodetected canvas size got printed - Added @ref Platform::WindowlessIosContext::glContext() for consistency with other context classes +- Undefining even more noise from `Xlib.h` (see + [mosra/magnum#498](https://github.com/mosra/magnum/pull/498)) @subsubsection changelog-latest-changes-shaders Shaders library From 729ab8d5e484fb23a7fd89689e29b99af08167a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Feb 2021 16:07:36 +0100 Subject: [PATCH 008/161] GL: StaticArray is no longer non-copyable. --- src/Magnum/GL/Context.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 0086d1238..81509cecd 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -670,16 +670,12 @@ Context::Context(Context&& other) noexcept: _version{other._version}, #ifndef MAGNUM_TARGET_WEBGL _flags{other._flags}, #endif - _extensionRequiredVersion{Containers::NoInit}, + _extensionRequiredVersion{other._extensionRequiredVersion}, _extensionStatus{other._extensionStatus}, _supportedExtensions{std::move(other._supportedExtensions)}, _state{std::move(other._state)}, _detectedDrivers{std::move(other._detectedDrivers)} { - /* StaticArray is deliberately non-copyable */ - for(std::size_t i = 0; i != Implementation::ExtensionCount; ++i) - _extensionRequiredVersion[i] = other._extensionRequiredVersion[i]; - if(currentContext == &other) currentContext = this; } From 95b3f8578d4862b5c6abba6a12dd6b015e795a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Feb 2021 17:43:35 +0100 Subject: [PATCH 009/161] GL: rework Context to not use any STL containers. We're going to eventually include this class in all Application classes (need that in order to inherit a to-be-created Configuration class) and the and would be just too much. This change caused magnum-gl-info.wasm (WebGL 2 build) to go down from 247 to 245 kB. Not much, but that's I guess because there's still a lot other vectors of strings elsewhere. There's a lot more places to clean up, will do those in separate commits. This change is the most atomic I could do, and it introduces a breaking change to all APIs that returned a std::vector or a std::string. Fortunately (or as I hope) those weren't used that much, so it shouldn't cause build breakages for that many people. Quite a lot of the optimization ideas is borrowed from the new Vk library -- such as "interning" the driver workaround strings to avoid allocating their copies. --- doc/changelog.dox | 14 ++ doc/snippets/MagnumPlatform-windowless.cpp | 2 +- doc/snippets/getting-started-blue.cpp | 2 +- src/Magnum/GL/Context.cpp | 223 +++++++++--------- src/Magnum/GL/Context.h | 62 +++-- src/Magnum/GL/Implementation/BufferState.cpp | 1 + src/Magnum/GL/Implementation/ContextState.cpp | 2 + .../GL/Implementation/FramebufferState.cpp | 2 + src/Magnum/GL/Implementation/MeshState.cpp | 2 + src/Magnum/GL/Implementation/QueryState.cpp | 2 + .../GL/Implementation/RendererState.cpp | 2 + .../GL/Implementation/ShaderProgramState.cpp | 2 + src/Magnum/GL/Implementation/ShaderState.cpp | 2 + src/Magnum/GL/Implementation/TextureState.cpp | 1 + .../GL/Implementation/driverSpecific.cpp | 195 ++++++++------- src/Magnum/GL/Test/ContextGLTest.cpp | 47 +++- .../Platform/WindowlessGlxApplication.cpp | 1 + .../Platform/WindowlessWglApplication.cpp | 1 + src/Magnum/Platform/gl-info.cpp | 4 +- src/Magnum/Shaders/Test/PhongGLTest.cpp | 11 +- .../OpenGL/GL/flextGLPlatform.cpp | 1 + .../OpenGL/GL/flextGLPlatform.cpp.template | 1 + 22 files changed, 356 insertions(+), 224 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index efb2fb9e8..3a715882f 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -458,6 +458,20 @@ See also: @ref Corrade::Containers::ArrayView are now removed. This should have a significant positive effect on compile times of code using the @ref GL, @ref Audio, @ref Trade and @ref Text libraries +- As part of the ongoing STL header dependency cleanup, + @ref GL::Context::vendorString(), + @relativeref{GL::Context,rendererString()}, + @relativeref{GL::Context,versionString()}, + @relativeref{GL::Context,shadingLanguageVersionString()}, + @relativeref{GL::Context,shadingLanguageVersionStrings()} and + @relativeref{GL::Context,extensionStrings()} now return + @relativeref{Corrade,Containers::StringView} or a + @relativeref{Corrade,Containers::Array} / + @relativeref{Corrade,Containers::ArrayView} of them, instead of a + @ref std::string and a @ref std::vector. For at least some backwards + compatibility the @ref Corrade/Containers/StringStl.h header is included to + provide implicit conversions to a @ref std::string, but in most cases + you'll be forced to change the code that uses those APIs. - @ref GL::TextureFormat::SR8 and @ref GL::TextureFormat::SRG8 were present on ES2 builds by mistake --- the @gl_extension{EXT,texture_sRGB_R8} and @gl_extension{EXT,texture_sRGB_RG8} extensions require OpenGL ES 3.0 at diff --git a/doc/snippets/MagnumPlatform-windowless.cpp b/doc/snippets/MagnumPlatform-windowless.cpp index 540684fec..17eff3276 100644 --- a/doc/snippets/MagnumPlatform-windowless.cpp +++ b/doc/snippets/MagnumPlatform-windowless.cpp @@ -24,7 +24,7 @@ */ /* [windowless] */ -#include +#include #include #include diff --git a/doc/snippets/getting-started-blue.cpp b/doc/snippets/getting-started-blue.cpp index 1385b487d..dba281b4f 100644 --- a/doc/snippets/getting-started-blue.cpp +++ b/doc/snippets/getting-started-blue.cpp @@ -26,7 +26,7 @@ #include #include /** [0] */ -#include +#include #include #include #include diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 81509cecd..4c825c516 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -26,13 +26,10 @@ #include "Context.h" #include -#include /* for initialization log redirection */ -#include #include +#include #include #include -#include -#include #include "Magnum/GL/AbstractFramebuffer.h" #include "Magnum/GL/AbstractShaderProgram.h" @@ -68,6 +65,8 @@ namespace Magnum { namespace GL { +using namespace Containers::Literals; + /* When adding a new list, Extension::extensions() and Context::Context() needs to be adapted. Binary search is performed on the extensions, thus they have to be sorted alphabetically. */ @@ -523,6 +522,44 @@ constexpr Extension ExtensionListES320[]{ #endif #undef _extension +constexpr struct { + Version version; + Containers::ArrayView extensions; +} KnownExtensionsForVersion[]{ + #ifndef MAGNUM_TARGET_GLES + {Version::GL300, Containers::arrayView(ExtensionList300)}, + {Version::GL310, Containers::arrayView(ExtensionList310)}, + {Version::GL320, Containers::arrayView(ExtensionList320)}, + {Version::GL330, Containers::arrayView(ExtensionList330)}, + {Version::GL400, Containers::arrayView(ExtensionList400)}, + {Version::GL410, Containers::arrayView(ExtensionList410)}, + {Version::GL420, Containers::arrayView(ExtensionList420)}, + {Version::GL430, Containers::arrayView(ExtensionList430)}, + {Version::GL440, Containers::arrayView(ExtensionList440)}, + {Version::GL450, Containers::arrayView(ExtensionList450)}, + {Version::GL460, Containers::arrayView(ExtensionList460)}, + #else + {Version::GLES300, Containers::arrayView(ExtensionListES300)}, + #ifndef MAGNUM_TARGET_WEBGL + /* No extensions in ES 3.1 */ + {Version::GLES320, Containers::arrayView(ExtensionListES320)}, + #endif + #endif + {Version::None, Containers::arrayView(ExtensionList)} +}; + +const Extension* findExtension(const Containers::StringView extension, const std::size_t since = 0) { + for(std::size_t i = since; i != Containers::arraySize(KnownExtensionsForVersion); ++i) { + const auto found = std::lower_bound(KnownExtensionsForVersion[i].extensions.begin(), KnownExtensionsForVersion[i].extensions.end(), extension, [](const Extension& a, const Containers::StringView& b) { + return a.string() < b; + }); + if(found != KnownExtensionsForVersion[i].extensions.end() && found->string() == extension) + return found; + } + + return {}; +} + } Containers::ArrayView Extension::extensions(Version version) { @@ -657,21 +694,39 @@ Context::Context(NoCreateT, Utility::Arguments& args, Int argc, const char** arg if(args.value("gpu-validation") == "on" || args.value("gpu-validation") == "ON") _internalFlags |= InternalFlag::GpuValidation; - /* Disable driver workarounds */ - for(auto&& workaround: Utility::String::splitWithoutEmptyParts(args.value("disable-workarounds"))) - disableDriverWorkaround(workaround); + /* If there are any disabled workarounds, save them until tryCreate() uses + them. The disableWorkaround() function saves the internal string view + instead of the one passed from the command line so we don't need to + bother with String allocations. */ + const Containers::StringView disabledWorkarounds = args.value("disable-workarounds"); + if(!disabledWorkarounds.isEmpty()) { + const Containers::Array split = disabledWorkarounds.splitWithoutEmptyParts(); + arrayReserve(_driverWorkarounds, split.size()); + for(const Containers::StringView workaround: split) + disableDriverWorkaround(workaround); + } - /* Disable extensions */ - for(auto&& extension: Utility::String::splitWithoutEmptyParts(args.value("disable-extensions"))) - _disabledExtensions.push_back(extension); + /* Disable extensions. Here we search for them among the known extensions + and store the Extension objects instead, which avoids the string copying + and another binary search in tryCreate(). */ + const Containers::StringView disabledExtensions = args.value("disable-extensions"); + if(!disabledExtensions.isEmpty()) { + const Containers::Array split = disabledExtensions.splitWithoutEmptyParts(); + arrayReserve(_disabledExtensions, split.size()); + for(const Containers::StringView extension: split) { + if(const Extension* found = findExtension(extension)) { + arrayAppend(_disabledExtensions, *found); + } + } + } } Context::Context(Context&& other) noexcept: _version{other._version}, #ifndef MAGNUM_TARGET_WEBGL _flags{other._flags}, #endif - _extensionRequiredVersion{other._extensionRequiredVersion}, _extensionStatus{other._extensionStatus}, + _extensionRequiredVersion{other._extensionRequiredVersion}, _supportedExtensions{std::move(other._supportedExtensions)}, _state{std::move(other._state)}, _detectedDrivers{std::move(other._detectedDrivers)} @@ -710,8 +765,8 @@ bool Context::tryCreate() { /* WebGL 2.0, treat it as ES 3.0 */ #else - const std::string version = versionString(); - if(version.find("WebGL 2") == std::string::npos) { + const Containers::StringView version = versionString(); + if(!version.contains("WebGL 2"_s)) { Error{} << "GL::Context: unsupported version string:" << version; return false; } @@ -738,17 +793,17 @@ bool Context::tryCreate() { #endif /* Allow ES2 context on driver that reports ES3 as supported */ - const std::string version = versionString(); + const Containers::StringView version = versionString(); #ifndef MAGNUM_TARGET_GLES - if(version.compare(0, 3, "2.1") == 0) + if(version.hasPrefix("2.1"_s)) #elif defined(MAGNUM_TARGET_WEBGL) /* Internet Explorer currently has 0.94 */ - if(version.find("WebGL 1") != std::string::npos || - version.find("WebGL 0") != std::string::npos) + if(version.contains("WebGL 1"_s) || + version.contains("WebGL 0"_s)) #else - if(version.find("OpenGL ES 2.0") != std::string::npos || + if(version.contains("OpenGL ES 2.0"_s) || /* It is possible to use Magnum compiled for ES2 on ES3 contexts */ - version.find("OpenGL ES 3.") != std::string::npos) + version.contains("OpenGL ES 3."_s)) #endif { majorVersion = 2; @@ -804,51 +859,22 @@ bool Context::tryCreate() { glGetIntegerv(GL_CONTEXT_FLAGS, reinterpret_cast(&_flags)); #endif - constexpr struct { - Version version; - Containers::ArrayView extensions; - } versions[]{ - #ifndef MAGNUM_TARGET_GLES - {Version::GL300, Containers::arrayView(ExtensionList300)}, - {Version::GL310, Containers::arrayView(ExtensionList310)}, - {Version::GL320, Containers::arrayView(ExtensionList320)}, - {Version::GL330, Containers::arrayView(ExtensionList330)}, - {Version::GL400, Containers::arrayView(ExtensionList400)}, - {Version::GL410, Containers::arrayView(ExtensionList410)}, - {Version::GL420, Containers::arrayView(ExtensionList420)}, - {Version::GL430, Containers::arrayView(ExtensionList430)}, - {Version::GL440, Containers::arrayView(ExtensionList440)}, - {Version::GL450, Containers::arrayView(ExtensionList450)}, - {Version::GL460, Containers::arrayView(ExtensionList460)}, - #else - {Version::GLES300, Containers::arrayView(ExtensionListES300)}, - #ifndef MAGNUM_TARGET_WEBGL - /* No extensions in ES 3.1 */ - {Version::GLES320, Containers::arrayView(ExtensionListES320)}, - #endif - #endif - {Version::None, Containers::arrayView(ExtensionList)} - }; - /* Get first future (not supported) version */ std::size_t future = 0; - while(versions[future].version != Version::None && isVersionSupported(versions[future].version)) + while(KnownExtensionsForVersion[future].version != Version::None && isVersionSupported(KnownExtensionsForVersion[future].version)) ++future; /* Mark all extensions from past versions as supported */ for(std::size_t i = 0; i != future; ++i) - for(const Extension& extension: versions[i].extensions) + for(const Extension& extension: KnownExtensionsForVersion[i].extensions) _extensionStatus.set(extension.index(), true); /* Check for presence of future and vendor extensions */ - const std::vector extensions = extensionStrings(); - for(const std::string& extension: extensions) { - for(std::size_t i = future; i != Containers::arraySize(versions); ++i) { - const auto found = std::lower_bound(versions[i].extensions.begin(), versions[i].extensions.end(), extension, [](const Extension& a, const std::string& b) { return a.string() < b; }); - if(found != versions[i].extensions.end() && found->string() == extension) { - _supportedExtensions.push_back(*found); - _extensionStatus.set(found->index(), true); - } + const Containers::Array extensions = extensionStrings(); + for(const Containers::StringView extension: extensions) { + if(const Extension* found = findExtension(extension, future)) { + arrayAppend(_supportedExtensions, *found); + _extensionStatus.set(found->index(), true); } } @@ -856,7 +882,7 @@ bool Context::tryCreate() { for(auto& i: _extensionRequiredVersion) i = Version::None; /* Initialize required versions from extension info */ - for(const auto& version: versions) + for(const auto& version: KnownExtensionsForVersion) for(const Extension& extension: version.extensions) _extensionRequiredVersion[extension.index()] = extension.requiredVersion(); @@ -873,31 +899,16 @@ bool Context::tryCreate() { /* Print some info and initialize state tracker (which also prints some more info). Mesa's renderer string has a space at the end, trim that. */ - Debug{output} << "Renderer:" << Utility::String::trim(rendererString()) << "by" << vendorString(); + Debug{output} << "Renderer:" << rendererString().trimmed() << "by" << vendorString(); Debug{output} << "OpenGL version:" << versionString(); /* Disable extensions as requested by the user */ if(!_disabledExtensions.empty()) { - bool headerPrinted = false; - - /* Disable extensions that are known and supported and print a message - for each */ - for(auto&& extension: _disabledExtensions) { - for(const auto& version: versions) { - const auto found = std::lower_bound(version.extensions.begin(), version.extensions.end(), extension, [](const Extension& a, const std::string& b) { return a.string() < b; }); - /* No error message here because some of the extensions could - be from Vulkan or OpenAL. That also means we print the - header only when we actually have something to say */ - if(found == version.extensions.end() || found->string() != extension) - continue; - - _extensionRequiredVersion[found->index()] = Version::None; - if(!headerPrinted) { - Debug{output} << "Disabling extensions:"; - headerPrinted = true; - } - Debug{output} << " " << extension; - } + Debug{output} << "Disabling extensions:"; + + for(const Extension& extension: _disabledExtensions) { + _extensionRequiredVersion[extension.index()] = Version::None; + Debug{output} << " " << extension.string(); } } @@ -939,45 +950,42 @@ bool Context::tryCreate() { return true; } -std::string Context::vendorString() const { - return Utility::String::fromArray(reinterpret_cast(glGetString(GL_VENDOR))); +Containers::StringView Context::vendorString() const { + return {reinterpret_cast(glGetString(GL_VENDOR)), Containers::StringViewFlag::Global}; } -std::string Context::rendererString() const { - return Utility::String::fromArray(reinterpret_cast(glGetString(GL_RENDERER))); +Containers::StringView Context::rendererString() const { + return {reinterpret_cast(glGetString(GL_RENDERER)), Containers::StringViewFlag::Global}; } -std::string Context::versionString() const { - return Utility::String::fromArray(reinterpret_cast(glGetString(GL_VERSION))); +Containers::StringView Context::versionString() const { + return {reinterpret_cast(glGetString(GL_VERSION)), Containers::StringViewFlag::Global}; } -std::string Context::shadingLanguageVersionString() const { - return Utility::String::fromArray(reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION))); +Containers::StringView Context::shadingLanguageVersionString() const { + return {reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)), Containers::StringViewFlag::Global}; } -std::vector Context::shadingLanguageVersionStrings() const { +Containers::Array Context::shadingLanguageVersionStrings() const { #ifndef MAGNUM_TARGET_GLES GLint versionCount = 0; glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS, &versionCount); - /* The implementation doesn't yet support this query (< OpenGL 4.3) */ - if(!versionCount) - return {shadingLanguageVersionString()}; - - /* Get all of them */ - std::vector versions; - versions.reserve(versionCount); - for(GLint i = 0; i != versionCount; ++i) - versions.emplace_back(reinterpret_cast(glGetStringi(GL_SHADING_LANGUAGE_VERSION, i))); - return versions; - #else - return {shadingLanguageVersionString()}; + /* If zero, the implementation doesn't yet support this query (< GL4.3) */ + /** @todo doesn't this throw a GL error? some better handling? */ + if(versionCount) { + /* Get all of them */ + Containers::Array versions{std::size_t(versionCount)}; + for(GLint i = 0; i != versionCount; ++i) + versions[i] = {reinterpret_cast(glGetStringi(GL_SHADING_LANGUAGE_VERSION, i)), Containers::StringViewFlag::Global}; + return versions; + } #endif -} -std::vector Context::extensionStrings() const { - std::vector extensions; + return Containers::array({shadingLanguageVersionString()}); +} +Containers::Array Context::extensionStrings() const { /* If we have GL 3.0 / GLES 3.0 at least, ask the new way. Otherwise don't even attempt to query GL_NUM_EXTENSIONS as that would cause a GL error on GL 2.1. Happens with Mesa's zink that's just 2.1 currently (Apr 2020) @@ -989,9 +997,10 @@ std::vector Context::extensionStrings() const { { GLint extensionCount = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); - extensions.reserve(extensionCount); + Containers::Array extensions{std::size_t(extensionCount)}; for(GLint i = 0; i != extensionCount; ++i) - extensions.emplace_back(reinterpret_cast(glGetStringi(GL_EXTENSIONS, i))); + extensions[i] = {reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)), Containers::StringViewFlag::Global}; + return extensions; } #ifndef MAGNUM_TARGET_GLES3 else @@ -1000,14 +1009,8 @@ std::vector Context::extensionStrings() const { #ifndef MAGNUM_TARGET_GLES3 /* OpenGL 2.1 / OpenGL ES 2.0 doesn't have glGetStringi() */ - { - /* Don't crash when glGetString() returns nullptr (i.e. don't trust the - old implementations) */ - extensions = Utility::String::splitWithoutEmptyParts(Utility::String::fromArray(reinterpret_cast(glGetString(GL_EXTENSIONS))), ' '); - } + return Containers::StringView{reinterpret_cast(glGetString(GL_EXTENSIONS)), Containers::StringViewFlag::Global}.splitWithoutEmptyParts(); #endif - - return extensions; } #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 655e8168a..8b42a55ef 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -30,12 +30,11 @@ */ #include -#include +#include #include #include #include #include -#include #include "Magnum/Magnum.h" #include "Magnum/Math/BoolVector.h" @@ -45,6 +44,12 @@ #include "Magnum/GL/visibility.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* For return types of Context::versionString() etc., which used to be a + std::string. Not ideal, but at least something. */ +#include +#endif + namespace Magnum { namespace GL { @@ -513,52 +518,62 @@ class MAGNUM_GL_EXPORT Context { * @brief Vendor string * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. + * OpenGL calls. The returned view is always + * @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and + * @relativeref{Corrade::Containers::StringViewFlag,Global}. * @see @ref rendererString(), @fn_gl{GetString} with * @def_gl_keyword{VENDOR} */ - std::string vendorString() const; + Containers::StringView vendorString() const; /** * @brief Renderer string * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. + * OpenGL calls. The returned view is always + * @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and + * @relativeref{Corrade::Containers::StringViewFlag,Global}. * @see @ref vendorString(), @fn_gl{GetString} with * @def_gl_keyword{RENDERER} */ - std::string rendererString() const; + Containers::StringView rendererString() const; /** * @brief Version string * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. + * OpenGL calls. The returned view is always + * @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and + * @relativeref{Corrade::Containers::StringViewFlag,Global}. * @see @ref shadingLanguageVersionString(), @ref version(), * @fn_gl{GetString} with @def_gl_keyword{VERSION} */ - std::string versionString() const; + Containers::StringView versionString() const; /** * @brief Shading language version string * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. + * OpenGL calls. The returned view is always + * @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and + * @relativeref{Corrade::Containers::StringViewFlag,Global}. * @see @ref versionString(), @ref version(), @fn_gl{GetString} with * @def_gl_keyword{SHADING_LANGUAGE_VERSION} */ - std::string shadingLanguageVersionString() const; + Containers::StringView shadingLanguageVersionString() const; /** * @brief Shading language version strings * * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. + * OpenGL calls. The returned view is always + * @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} and + * @relativeref{Corrade::Containers::StringViewFlag,Global}. * @see @ref versionString(), @ref version(), @fn_gl{Get} with * @def_gl_keyword{NUM_SHADING_LANGUAGE_VERSIONS}, @fn_gl{GetString} * with @def_gl_keyword{SHADING_LANGUAGE_VERSION} */ - std::vector shadingLanguageVersionStrings() const; + Containers::Array shadingLanguageVersionStrings() const; /** * @brief Extension strings @@ -567,11 +582,13 @@ class MAGNUM_GL_EXPORT Context { * OpenGL calls. Note that this function returns list of all extensions * reported by the driver (even those not supported by Magnum), see * @ref supportedExtensions(), @ref Extension::extensions() or - * @ref isExtensionSupported() for alternatives. + * @ref isExtensionSupported() for alternatives. The returned views are + * always @relativeref{Corrade,Containers::StringViewFlag::NullTerminated} + * and @relativeref{Corrade::Containers::StringViewFlag,Global}. * @see @fn_gl{Get} with @def_gl_keyword{NUM_EXTENSIONS}, * @fn_gl{GetString} with @def_gl_keyword{EXTENSIONS} */ - std::vector extensionStrings() const; + Containers::Array extensionStrings() const; #ifndef MAGNUM_TARGET_WEBGL /** @@ -589,7 +606,7 @@ class MAGNUM_GL_EXPORT Context { * the current. * @see @ref isExtensionSupported(), @ref Extension::extensions() */ - const std::vector& supportedExtensions() const { + Containers::ArrayView supportedExtensions() const { return _supportedExtensions; } @@ -750,7 +767,7 @@ class MAGNUM_GL_EXPORT Context { typedef Containers::EnumSet InternalFlags; CORRADE_ENUMSET_FRIEND_OPERATORS(InternalFlags) - bool isDriverWorkaroundDisabled(const char* workaround); + bool isDriverWorkaroundDisabled(Containers::StringView workaround); Implementation::State& state() { return *_state; } /* This function is called from MeshState constructor, which means the @@ -778,7 +795,7 @@ class MAGNUM_GL_EXPORT Context { friend Implementation::ContextState; #endif - void disableDriverWorkaround(const std::string& workaround); + void disableDriverWorkaround(Containers::StringView workaround); /* Defined in Implementation/driverSpecific.cpp */ MAGNUM_GL_LOCAL void setupDriverWorkarounds(); @@ -794,17 +811,20 @@ class MAGNUM_GL_EXPORT Context { Flags _flags; #endif - Containers::StaticArray _extensionRequiredVersion; Math::BoolVector _extensionStatus; - std::vector _supportedExtensions; + /* For all extensions that are marked as supported in _extensionStatus, + this field contains the minimal required GL version the extension + needs. Extensions that are disabled have None here. */ + Containers::StaticArray _extensionRequiredVersion; + Containers::Array _supportedExtensions; Containers::Pointer _state; Containers::Optional _detectedDrivers; /* True means known and disabled, false means known */ - std::vector> _driverWorkarounds; - std::vector _disabledExtensions; + Containers::Array> _driverWorkarounds; + Containers::Array _disabledExtensions; InternalFlags _internalFlags; }; diff --git a/src/Magnum/GL/Implementation/BufferState.cpp b/src/Magnum/GL/Implementation/BufferState.cpp index 1ecf23caf..c3b056da7 100644 --- a/src/Magnum/GL/Implementation/BufferState.cpp +++ b/src/Magnum/GL/Implementation/BufferState.cpp @@ -25,6 +25,7 @@ #include "BufferState.h" +#include #include #include "Magnum/GL/Context.h" diff --git a/src/Magnum/GL/Implementation/ContextState.cpp b/src/Magnum/GL/Implementation/ContextState.cpp index ca1343fec..da6478547 100644 --- a/src/Magnum/GL/Implementation/ContextState.cpp +++ b/src/Magnum/GL/Implementation/ContextState.cpp @@ -25,6 +25,8 @@ #include "ContextState.h" +#include + #include "Magnum/GL/Context.h" namespace Magnum { namespace GL { namespace Implementation { diff --git a/src/Magnum/GL/Implementation/FramebufferState.cpp b/src/Magnum/GL/Implementation/FramebufferState.cpp index b884a9c33..1f07ca2e5 100644 --- a/src/Magnum/GL/Implementation/FramebufferState.cpp +++ b/src/Magnum/GL/Implementation/FramebufferState.cpp @@ -25,6 +25,8 @@ #include "FramebufferState.h" +#include + #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" #include "Magnum/GL/Renderbuffer.h" diff --git a/src/Magnum/GL/Implementation/MeshState.cpp b/src/Magnum/GL/Implementation/MeshState.cpp index 1f5075893..c5320a2ee 100644 --- a/src/Magnum/GL/Implementation/MeshState.cpp +++ b/src/Magnum/GL/Implementation/MeshState.cpp @@ -25,6 +25,8 @@ #include "MeshState.h" +#include + #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" #include "Magnum/GL/MeshView.h" diff --git a/src/Magnum/GL/Implementation/QueryState.cpp b/src/Magnum/GL/Implementation/QueryState.cpp index 64d97475a..b2c4606a5 100644 --- a/src/Magnum/GL/Implementation/QueryState.cpp +++ b/src/Magnum/GL/Implementation/QueryState.cpp @@ -25,6 +25,8 @@ #include "QueryState.h" +#include + #include "Magnum/GL/AbstractQuery.h" #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" diff --git a/src/Magnum/GL/Implementation/RendererState.cpp b/src/Magnum/GL/Implementation/RendererState.cpp index 666b3a2d9..1e909a992 100644 --- a/src/Magnum/GL/Implementation/RendererState.cpp +++ b/src/Magnum/GL/Implementation/RendererState.cpp @@ -25,6 +25,8 @@ #include "RendererState.h" +#include + #include "Magnum/PixelStorage.h" #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.cpp b/src/Magnum/GL/Implementation/ShaderProgramState.cpp index 99ca2545f..1ca259ff8 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/GL/Implementation/ShaderProgramState.cpp @@ -25,6 +25,8 @@ #include "ShaderProgramState.h" +#include + #include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" diff --git a/src/Magnum/GL/Implementation/ShaderState.cpp b/src/Magnum/GL/Implementation/ShaderState.cpp index 8339e5069..762514c32 100644 --- a/src/Magnum/GL/Implementation/ShaderState.cpp +++ b/src/Magnum/GL/Implementation/ShaderState.cpp @@ -27,6 +27,8 @@ /* Needed only for Emscripten+pthread- / Windows+Intel-specific workarounds, but I won't bother crafting the preprocessor logic for this. */ +#include + #include "Magnum/GL/Context.h" #include "Magnum/GL/Shader.h" diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index 22534e671..a0502c123 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -26,6 +26,7 @@ #include "TextureState.h" #include +#include #include #include "Magnum/GL/AbstractTexture.h" diff --git a/src/Magnum/GL/Implementation/driverSpecific.cpp b/src/Magnum/GL/Implementation/driverSpecific.cpp index 6d06c3749..45ef76398 100644 --- a/src/Magnum/GL/Implementation/driverSpecific.cpp +++ b/src/Magnum/GL/Implementation/driverSpecific.cpp @@ -23,11 +23,8 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include -#include -#include -#include +#include +#include #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" @@ -37,14 +34,16 @@ namespace Magnum { namespace GL { namespace { -/* Search the code for the following strings to see where they are implemented. */ -const char* KnownWorkarounds[]{ +using namespace Containers::Literals; + +/* Search the code for the following strings to see where they are implemented */ +constexpr Containers::StringView KnownWorkarounds[]{ /* [workarounds] */ #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) /* ANGLE's shader linker insists on returning a message consisting of a single newline on success, causing annoying noise in the console. Similar to "intel-windows-chatty-shader-compiler". */ -"angle-chatty-shader-compiler", +"angle-chatty-shader-compiler"_s, #endif #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) @@ -69,7 +68,7 @@ const char* KnownWorkarounds[]{ data modification on *any* buffer, which would have extreme perf implications. So FORTUNATELY unbinding the textures worked around this too, and is a much nicer workaround after all. */ -"apple-buffer-texture-unbind-on-buffer-modify", +"apple-buffer-texture-unbind-on-buffer-modify"_s, #endif #if defined(CORRADE_TARGET_ANDROID) && defined(MAGNUM_TARGET_GLES) @@ -77,7 +76,7 @@ const char* KnownWorkarounds[]{ running from the Android shell (through ADB). No such error happens in an APK. Detecting using the $SHELL environment variable and disabling GL_EXT_disjoint_timer_query in that case. */ -"arm-mali-timer-queries-oom-in-shell", +"arm-mali-timer-queries-oom-in-shell"_s, #endif #if !defined(MAGNUM_TARGET_GLES) && defined(CORRADE_TARGET_WINDOWS) @@ -90,30 +89,30 @@ const char* KnownWorkarounds[]{ svga3d-texture-upload-slice-by-slice workaround. The compressed image up/ download is affected as well, but we lack APIs for easy format-dependent slicing and offset calculation, so those currently still fail. */ -"amd-windows-cubemap-image3d-slice-by-slice", +"amd-windows-cubemap-image3d-slice-by-slice"_s, /* AMD Windows drivers have broken the DSA glCopyTextureSubImage3D(), returning GL_INVALID_VALUE. The non-DSA code path works. */ -"amd-windows-broken-dsa-cubemap-copy", +"amd-windows-broken-dsa-cubemap-copy"_s, /* AMD Windows glCreateQueries() works for everything except GL_TRANSFORM_FEEDBACK_[STREAM_]OVERFLOW, probably they just forgot to adapt it to this new GL 4.6 addition. Calling the non-DSA code path in that case instead. Similar to "mesa-dsa-createquery-except-pipeline-stats". */ -"amd-windows-dsa-createquery-except-xfb-overflow", +"amd-windows-dsa-createquery-except-xfb-overflow"_s, #endif #if !defined(MAGNUM_TARGET_GLES) && !defined(CORRADE_TARGET_APPLE) /* Creating core context with specific version on AMD and NV proprietary drivers on Linux/Windows and Intel drivers on Windows causes the context to be forced to given version instead of selecting latest available version */ -"no-forward-compatible-core-context", +"no-forward-compatible-core-context"_s, #endif #if !defined(MAGNUM_TARGET_GLES) && defined(CORRADE_TARGET_WINDOWS) /* On Windows Intel drivers ARB_shading_language_420pack is exposed in GLSL even though the extension (e.g. binding keyword) is not supported */ -"intel-windows-glsl-exposes-unsupported-shading-language-420pack", +"intel-windows-glsl-exposes-unsupported-shading-language-420pack"_s, #endif #ifndef MAGNUM_TARGET_GLES @@ -121,12 +120,12 @@ const char* KnownWorkarounds[]{ ARB_pipeline_statistics_query, probably just forgotten. Calling the non-DSA code path in that case instead. Similar to "amd-windows-dsa-createquery-except-xfb-overflow". */ -"mesa-dsa-createquery-except-pipeline-stats", +"mesa-dsa-createquery-except-pipeline-stats"_s, /* Forward-compatible GL contexts on Mesa still report line width range as [1, 7], but setting wide line width fails. According to the specs the max value on forward compatible contexts should be 1.0, so patching it. */ -"mesa-forward-compatible-line-width-range", +"mesa-forward-compatible-line-width-range"_s, #endif #if !defined(MAGNUM_TARGET_GLES2) && defined(CORRADE_TARGET_WINDOWS) @@ -135,31 +134,31 @@ const char* KnownWorkarounds[]{ arrays are not in scope anymore. Enabling *synchronous* debug output circumvents this bug. Can be triggered by running TransformFeedbackGLTest with GL_KHR_debug extension disabled. */ -"nv-windows-dangling-transform-feedback-varying-names", +"nv-windows-dangling-transform-feedback-varying-names"_s, #endif #ifndef MAGNUM_TARGET_GLES /* Layout qualifier causes compiler error with GLSL 1.20 on Mesa, GLSL 1.30 on NVidia and 1.40 on macOS. Everything is fine when using a newer GLSL version. */ -"no-layout-qualifiers-on-old-glsl", +"no-layout-qualifiers-on-old-glsl"_s, /* NVidia drivers (358.16) report compressed block size from internal format query in bits instead of bytes */ -"nv-compressed-block-size-in-bits", +"nv-compressed-block-size-in-bits"_s, /* NVidia drivers (358.16) report different compressed image size for cubemaps based on whether the texture is immutable or not and not based on whether I'm querying all faces (ARB_DSA) or a single face (non-DSA, EXT_DSA) */ -"nv-cubemap-inconsistent-compressed-image-size", +"nv-cubemap-inconsistent-compressed-image-size"_s, /* NVidia drivers (358.16) return only the first slice of compressed cube map image when querying all six slices using the ARB_DSA API */ -"nv-cubemap-broken-full-compressed-image-query", +"nv-cubemap-broken-full-compressed-image-query"_s, /* NVidia drivers return 0 when asked for GL_CONTEXT_PROFILE_MASK, so it needs to be worked around by asking for GL_ARB_compatibility */ -"nv-zero-context-profile-mask", +"nv-zero-context-profile-mask"_s, /* (Headless) EGL contexts for desktop GL on NVidia 384 and 390 drivers don't have correct statically linked GL 1.0 and 1.1 functions (such as @@ -167,7 +166,7 @@ const char* KnownWorkarounds[]{ eglGetProcAddress(). Doesn't seem to happen on pre-384 and 396, but it's not possible to get driver version through EGL, so enabling this unconditionally on all EGL NV contexts. */ -"nv-egl-incorrect-gl11-function-pointers", +"nv-egl-incorrect-gl11-function-pointers"_s, /* On NV driver 450.80.02, eglQueryDeviceAttribEXT() segfaults when querying GPUs that the user does not have access to (i.e. via cgroup). Instead, @@ -175,19 +174,19 @@ const char* KnownWorkarounds[]{ error that can be retrieved via eglGetError() to see if the user has access to that device. On well-behaved driver versions, eglQueryDeviceAttribEXT() returns false instead of segfaulting. */ -"nv-egl-crashy-query-device-attrib", +"nv-egl-crashy-query-device-attrib"_s, #endif #ifndef MAGNUM_TARGET_GLES /* SVGA3D (VMware host GL driver) glDrawArrays() draws nothing when the vertex buffer memory is initialized using glNamedBufferData() from ARB_DSA. Using the non-DSA glBufferData() works. */ -"svga3d-broken-dsa-bufferdata", +"svga3d-broken-dsa-bufferdata"_s, /* SVGA3D does out-of-bound writes in some cases of glGetTexSubImage(), leading to memory corruption on client machines. That's nasty, so the whole ARB_get_texture_sub_image is disabled. */ -"svga3d-gettexsubimage-oob-write", +"svga3d-gettexsubimage-oob-write"_s, #endif /* SVGA3D has broken handling of glTex[ture][Sub]Image*D() for 1D arrays, 2D @@ -196,25 +195,25 @@ const char* KnownWorkarounds[]{ with buffer images. Seems to be fixed in Mesa 13, but I have no such system to verify that on. https://github.com/mesa3d/mesa/commit/2aa9ff0cda1f6ad97c83d5583fab7a84efabe19e */ -"svga3d-texture-upload-slice-by-slice", +"svga3d-texture-upload-slice-by-slice"_s, #if defined(CORRADE_TARGET_EMSCRIPTEN) && defined(__EMSCRIPTEN_PTHREADS__) /* Shader sources containing UTF-8 characters are converted to empty strings when running on Emscripten with -s USE_PTHREADS=1. Working around that by replacing all chars > 127 with spaces. Relevant code: https://github.com/kripken/emscripten/blob/7f89560101843198787530731f40a65288f6f15f/src/fetch-worker.js#L54-L58 */ -"emscripten-pthreads-broken-unicode-shader-sources", +"emscripten-pthreads-broken-unicode-shader-sources"_s, #endif #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) /* Empty EGL_CONTEXT_FLAGS_KHR cause SwiftShader 3.3.0.1 to fail context creation with EGL_BAD_ATTRIBUTE. Not sending the flags then. Relevant code: https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L810 */ -"swiftshader-no-empty-egl-context-flags", +"swiftshader-no-empty-egl-context-flags"_s, /* SwiftShader 3.3.0.1 crashes deep inside eglMakeCurrent() when using EGL_NO_SURFACE. Supplying a 32x32 PBuffer to work around that. */ -"swiftshader-egl-context-needs-pbuffer", +"swiftshader-egl-context-needs-pbuffer"_s, #endif #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -225,14 +224,14 @@ const char* KnownWorkarounds[]{ ES3. OTOH, glVertexAttribDivisor is there for both ANGLE and EXT. Relevant code: https://github.com/google/swiftshader/blob/ad5c2952ca88730c07e04f6f1566194b66860c26/src/OpenGL/libGLESv2/libGLESv2.cpp#L6352-L6357 Disabling the two extensions on ES2 contexts to avoid nullptr crashes. */ -"swiftshader-no-es2-draw-instanced-entrypoints", +"swiftshader-no-es2-draw-instanced-entrypoints"_s, /* SwiftShader 4.1.0 on ES2 contexts reports GL_OES_texture_3D but from all its entrypoints only glTexImage3DOES is present, all others are present only in the ES3 unsuffixed versions. Relevant code: https://github.com/google/swiftshader/blob/ad5c2952ca88730c07e04f6f1566194b66860c26/src/OpenGL/libGLESv2/libGLESv2.cpp#L6504 Disabling the extension on ES2 contexts to avoid nullptr crashes. */ -"swiftshader-no-es2-oes-texture-3d-entrypoints", +"swiftshader-no-es2-oes-texture-3d-entrypoints"_s, #endif #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -242,14 +241,14 @@ const char* KnownWorkarounds[]{ otherwise. No other driver does that. As a workaround, setting Buffer::TargetHint::TransformFeedback will make it use Buffer::TargetHint::Array instead, as that works okay. */ -"swiftshader-broken-xfb-buffer-binding-target", +"swiftshader-broken-xfb-buffer-binding-target"_s, /* SwiftShader 4.1.0 does implement gl_VertexID for ES3 contexts, but in practice it doesn't work, returning a constant value. In order to make this easier to check, there's a dummy MAGNUM_shader_vertex_id extension that's defined on all GL 3.0+ and GLES 3.0+ / WebGL 2+ contexts *except* for SwiftShader. */ -"swiftshader-broken-shader-vertex-id", +"swiftshader-broken-shader-vertex-id"_s, #endif #ifndef MAGNUM_TARGET_GLES @@ -258,7 +257,7 @@ const char* KnownWorkarounds[]{ bound for reading. Relevant code: https://github.com/mesa3d/mesa/blob/212c0c630a849e4737e2808a993d708cbb2f18f7/src/mesa/main/framebuffer.c#L841-L843 Workaround is to explicitly bind the framebuffer for reading. */ -"mesa-implementation-color-read-format-dsa-explicit-binding", +"mesa-implementation-color-read-format-dsa-explicit-binding"_s, #endif #if !defined(MAGNUM_TARGET_GLES2) && defined(CORRADE_TARGET_WINDOWS) @@ -272,7 +271,7 @@ const char* KnownWorkarounds[]{ glGetInteger() is actually able to return a correct value in *one circumstance*, it's preferrable to the other random shit the driver is doing. */ -"intel-windows-implementation-color-read-format-completely-broken", +"intel-windows-implementation-color-read-format-completely-broken"_s, #endif #if !defined(MAGNUM_TARGET_GLES) && defined(CORRADE_TARGET_WINDOWS) @@ -306,8 +305,8 @@ const char* KnownWorkarounds[]{ on DSA that's not there. It's clearly Intel drivers fault. - With both enabled, things seem to be fine, and I hope it stays that way also for future driver updates. */ -"intel-windows-crazy-broken-buffer-dsa", -"intel-windows-crazy-broken-vao-dsa", +"intel-windows-crazy-broken-buffer-dsa"_s, +"intel-windows-crazy-broken-vao-dsa"_s, /* ARB_direct_state_access implementation on Intel Windows drivers has broken *everything* related to cube map textures (but not cube map arrays) -- data @@ -315,37 +314,37 @@ const char* KnownWorkarounds[]{ complaining about "Wrong 6 provided for 34067" and similar (GL_TEXTURE_CUBE_MAP is 34067). Using the non-DSA code paths as a workaround (for the 3D image up/download as well). */ -"intel-windows-broken-dsa-for-cubemaps", +"intel-windows-broken-dsa-for-cubemaps"_s, /* DSA glBindTextureUnit() on Intel Windows drivers simply doesn't work when passing 0 to it. Non-zero IDs work correctly except for cube maps. Using the non-DSA code path for unbinding and cube maps as a workaround. */ -"intel-windows-half-baked-dsa-texture-bind", +"intel-windows-half-baked-dsa-texture-bind"_s, /* DSA glNamedFramebufferTexture() on Intel Windows drivers doesn't work for layered cube map array attachments. Non-layered or non-array cube map attachment works. Using the non-DSA code path as a workaround. */ -"intel-windows-broken-dsa-layered-cubemap-array-framebuffer-attachment", +"intel-windows-broken-dsa-layered-cubemap-array-framebuffer-attachment"_s, /* DSA glClearNamedFramebuffer*() on Intel Windows drivers doesn't do anything. Using the non-DSA code path as a workaournd. */ -"intel-windows-broken-dsa-framebuffer-clear", +"intel-windows-broken-dsa-framebuffer-clear"_s, /* Using DSA glCreateQueries() on Intel Windows drivers breaks glBeginQueryIndexed(). Using the non-DSA glGenQueries() instead makes it work properly. See TransformFeedbackGLTest for a test. */ -"intel-windows-broken-dsa-indexed-queries", +"intel-windows-broken-dsa-indexed-queries"_s, /* DSA-ified "vertex layout" glVertexArrayAttribIFormat() is broken when passing shorts instead of full 32bit ints. Using the old-style glVertexAttribIPointer() works correctly. No idea if the non-DSA glVertexAttribIFormat() works or not. A test that triggers this issue is in MeshGLTest::addVertexBufferIntWithShort(). */ -"intel-windows-broken-dsa-integer-vertex-attributes", +"intel-windows-broken-dsa-integer-vertex-attributes"_s, /* Shader compiler on Intel Windows drivers insists on telling me "No errors." when it should just stay silent. See also "angle-chatty-shader-compiler". */ -"intel-windows-chatty-shader-compiler", +"intel-windows-chatty-shader-compiler"_s, /* When using more than just a vertex and fragment shader (geometry shader, e.g.), ARB_explicit_uniform_location on Intel silently uses wrong @@ -359,7 +358,7 @@ const char* KnownWorkarounds[]{ location 1, setting color to location 2 didn't work, ending up with a Generic error again (driver version 27). Because this is impossible to prevent, the extension is completely disabled on all Intel Windows drivers. */ -"intel-windows-explicit-uniform-location-is-less-explicit-than-you-hoped", +"intel-windows-explicit-uniform-location-is-less-explicit-than-you-hoped"_s, #endif #ifndef MAGNUM_TARGET_GLES @@ -367,13 +366,13 @@ const char* KnownWorkarounds[]{ GL_IMPLEMENTATION_COLOR_READ_FORMAT and _TYPE is queried using glGetNamedFramebufferParameter(). Using either glGetInteger() or glGetFramebufferParameter() works correctly. */ -"nv-implementation-color-read-format-dsa-broken", +"nv-implementation-color-read-format-dsa-broken"_s, #endif #ifndef MAGNUM_TARGET_GLES /* ApiTrace needs an explicit initial glViewport() call to initialize its framebuffer size, otherwise it assumes it's zero-sized. */ -"apitrace-zero-initial-viewport", +"apitrace-zero-initial-viewport"_s, #endif #if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) @@ -386,11 +385,29 @@ const char* KnownWorkarounds[]{ https://www.khronos.org/webgl/public-mailing-list/public_webgl/1705/msg00015.php and https://github.com/emscripten-core/emscripten/pull/9652 for the Emscripten-side part of this workaround. */ -"firefox-fake-disjoint-timer-query-webgl2", +"firefox-fake-disjoint-timer-query-webgl2"_s, #endif /* [workarounds] */ }; +/* I could use std::find(), right? Well, it'd be a whole lot more typing and + an #include *and* #include or whatever as well, + because apparently ONE CAN'T GET std::begin() / std::end() without including + tens thousands lines of irrelevant shit, FFS. + + Also the comparison to array end to discover if it wasn't found is just a + useless verbose crap shit as well, so we'll do better here and return a null + view instead. + + Since the workaround list isn't really huge for an average platform (16 on + Linux, Windows probably ~30?) and there's very few used heavily, I won't + bother with some binary search, which needs extra testing effort. */ +Containers::StringView findWorkaround(Containers::StringView workaround) { + for(Containers::StringView i: KnownWorkarounds) + if(workaround == i) return i; + return {}; +} + } auto Context::detectedDriver() -> DetectedDrivers { @@ -398,33 +415,33 @@ auto Context::detectedDriver() -> DetectedDrivers { _detectedDrivers = DetectedDrivers{}; - const std::string renderer = rendererString(); - const std::string vendor = vendorString(); - const std::string version = versionString(); + const Containers::StringView renderer = rendererString(); + const Containers::StringView vendor = vendorString(); + const Containers::StringView version = versionString(); /* Apple has its own drivers */ #if !defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_WEBGL) /* AMD binary desktop drivers */ - if(vendor.find("ATI Technologies Inc.") != std::string::npos) + if(vendor.contains("ATI Technologies Inc."_s)) return *_detectedDrivers |= DetectedDriver::Amd; #ifdef CORRADE_TARGET_WINDOWS /* Intel Windows drivers */ - if(vendor.find("Intel") != std::string::npos) + if(vendor.contains("Intel"_s)) return *_detectedDrivers |= DetectedDriver::IntelWindows; #endif /* Mesa drivers */ - if(version.find("Mesa") != std::string::npos) { + if(version.contains("Mesa"_s)) { *_detectedDrivers |= DetectedDriver::Mesa; - if(renderer.find("SVGA3D") != std::string::npos) + if(renderer.contains("SVGA3D"_s)) *_detectedDrivers |= DetectedDriver::Svga3D; return *_detectedDrivers; } - if(vendor.find("NVIDIA Corporation") != std::string::npos) + if(vendor.contains("NVIDIA Corporation"_s)) return *_detectedDrivers |= DetectedDriver::NVidia; #endif @@ -433,53 +450,63 @@ auto Context::detectedDriver() -> DetectedDrivers { /* ANGLE. Can detect easily on ES, have to resort to hacks on WebGL. Sources: http://stackoverflow.com/a/20149090 + http://webglreport.com */ #ifndef MAGNUM_TARGET_WEBGL - if(renderer.find("ANGLE") != std::string::npos) + if(renderer.contains("ANGLE"_s)) return *_detectedDrivers |= DetectedDriver::Angle; #else { Range1Di range; glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, range.data()); - if(range.min() == 1 && range.max() == 1 && vendor != "Internet Explorer") + if(range.min() == 1 && range.max() == 1 && vendor != "Internet Explorer"_s) return *_detectedDrivers |= DetectedDriver::Angle; } #endif #ifndef MAGNUM_TARGET_WEBGL /* SwiftShader */ - if(renderer.find("SwiftShader") != std::string::npos) + if(renderer.contains("SwiftShader"_s)) return *_detectedDrivers |= DetectedDriver::SwiftShader; #endif #endif #ifdef CORRADE_TARGET_ANDROID - if(vendor.find("ARM") != std::string::npos && renderer.find("Mali") != std::string::npos) + if(vendor.contains("ARM"_s) && renderer.contains("Mali"_s)) return *_detectedDrivers |= DetectedDriver::ArmMali; #endif return *_detectedDrivers; } -void Context::disableDriverWorkaround(const std::string& workaround) { +void Context::disableDriverWorkaround(const Containers::StringView workaround) { + /* Find the workaround. Note that we'll add the found view to the array + and not the passed view, as the found view is guaranteed to stay in + scope */ + const Containers::StringView found = findWorkaround(workaround); + /* Ignore unknown workarounds */ /** @todo this will probably cause false positives when both GL and Vulkan is used together? */ - if(std::find(std::begin(KnownWorkarounds), std::end(KnownWorkarounds), workaround) == std::end(KnownWorkarounds)) { - Warning() << "GL: unknown workaround" << workaround; + if(found.isEmpty()) { + Warning{} << "GL: unknown workaround" << workaround; return; } - _driverWorkarounds.emplace_back(workaround, true); + + arrayAppend(_driverWorkarounds, Containers::InPlaceInit, found, true); } -bool Context::isDriverWorkaroundDisabled(const char* workaround) { - CORRADE_INTERNAL_ASSERT(std::find_if(std::begin(KnownWorkarounds), std::end(KnownWorkarounds), [&](const char* a) { - return std::strcmp(a, workaround) == 0; - }) != std::end(KnownWorkarounds)); +bool Context::isDriverWorkaroundDisabled(const Containers::StringView workaround) { + /* Find the workaround. Note that we'll add the found view to the array + and not the passed view, as the found view is guaranteed to stay in + scope */ + Containers::StringView found = findWorkaround(workaround); + CORRADE_INTERNAL_ASSERT(!found.isEmpty()); /* If the workaround was already asked for or disabled, return its state, - otherwise add it to the list as used one */ + otherwise add it to the list as used one. Here we again cheat a bit and + compare just data pointers instead of the whole string as we store only + the views in the KnownWorkarounds list. */ for(const auto& i: _driverWorkarounds) - if(i.first == workaround) return i.second; - _driverWorkarounds.emplace_back(workaround, false); + if(i.first.data() == found.data()) return i.second; + arrayAppend(_driverWorkarounds, Containers::InPlaceInit, found, false); return false; } @@ -489,17 +516,17 @@ void Context::setupDriverWorkarounds() { _extensionRequiredVersion[Extensions::extension::Index] = Version::version #ifndef MAGNUM_TARGET_GLES - if(!isDriverWorkaroundDisabled("no-layout-qualifiers-on-old-glsl")) { + if(!isDriverWorkaroundDisabled("no-layout-qualifiers-on-old-glsl"_s)) { _setRequiredVersion(ARB::explicit_attrib_location, GL320); _setRequiredVersion(ARB::explicit_uniform_location, GL320); _setRequiredVersion(ARB::shading_language_420pack, GL320); } #ifdef CORRADE_TARGET_WINDOWS - if((detectedDriver() & DetectedDriver::IntelWindows) && !isExtensionSupported() && !isDriverWorkaroundDisabled("intel-windows-glsl-exposes-unsupported-shading-language-420pack")) + if((detectedDriver() & DetectedDriver::IntelWindows) && !isExtensionSupported() && !isDriverWorkaroundDisabled("intel-windows-glsl-exposes-unsupported-shading-language-420pack"_s)) _setRequiredVersion(ARB::shading_language_420pack, None); - if((detectedDriver() & DetectedDriver::IntelWindows) && isExtensionSupported() && !isDriverWorkaroundDisabled("intel-windows-explicit-uniform-location-is-less-explicit-than-you-hoped")) { + if((detectedDriver() & DetectedDriver::IntelWindows) && isExtensionSupported() && !isDriverWorkaroundDisabled("intel-windows-explicit-uniform-location-is-less-explicit-than-you-hoped"_s)) { _setRequiredVersion(ARB::explicit_uniform_location, None); } #endif @@ -508,7 +535,7 @@ void Context::setupDriverWorkarounds() { #ifndef MAGNUM_TARGET_GLES if((detectedDriver() & DetectedDriver::Svga3D) && isExtensionSupported() && - !isDriverWorkaroundDisabled("svga3d-gettexsubimage-oob-write")) + !isDriverWorkaroundDisabled("svga3d-gettexsubimage-oob-write"_s)) _setRequiredVersion(ARB::get_texture_sub_image, None); #endif @@ -516,26 +543,26 @@ void Context::setupDriverWorkarounds() { if(detectedDriver() & Context::DetectedDriver::SwiftShader) { if((isExtensionSupported() || isExtensionSupported()) && - !isDriverWorkaroundDisabled("swiftshader-no-es2-draw-instanced-entrypoints")) { + !isDriverWorkaroundDisabled("swiftshader-no-es2-draw-instanced-entrypoints"_s)) { _setRequiredVersion(ANGLE::instanced_arrays, None); _setRequiredVersion(EXT::instanced_arrays, None); } if(isExtensionSupported() && - !isDriverWorkaroundDisabled("swiftshader-no-es2-oes-texture-3d-entrypoints")) + !isDriverWorkaroundDisabled("swiftshader-no-es2-oes-texture-3d-entrypoints"_s)) _setRequiredVersion(OES::texture_3D, None); } #endif #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) if((detectedDriver() & Context::DetectedDriver::SwiftShader) && - !isDriverWorkaroundDisabled("swiftshader-broken-shader-vertex-id")) + !isDriverWorkaroundDisabled("swiftshader-broken-shader-vertex-id"_s)) _setRequiredVersion(MAGNUM::shader_vertex_id, None); #endif #if defined(CORRADE_TARGET_ANDROID) && defined(MAGNUM_TARGET_GLES) if((detectedDriver() & Context::DetectedDriver::ArmMali) && - std::getenv("SHELL") && !isDriverWorkaroundDisabled("arm-mali-timer-queries-oom-in-shell")) + std::getenv("SHELL") && !isDriverWorkaroundDisabled("arm-mali-timer-queries-oom-in-shell"_s)) _setRequiredVersion(EXT::disjoint_timer_query, None); #endif @@ -565,7 +592,7 @@ void Context::setupDriverWorkarounds() { #ifndef MAGNUM_TARGET_GLES if(isExtensionSupported() && - !isDriverWorkaroundDisabled("apitrace-zero-initial-viewport")) { + !isDriverWorkaroundDisabled("apitrace-zero-initial-viewport"_s)) { GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); @@ -573,9 +600,9 @@ void Context::setupDriverWorkarounds() { #endif #if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) - if(rendererString() == "Mozilla") { + if(rendererString() == "Mozilla"_s) { for(const auto& extension: extensionStrings()) { - if(extension == "GL_EXT_disjoint_timer_query" && !isDriverWorkaroundDisabled("firefox-fake-disjoint-timer-query-webgl2")) { + if(extension == "GL_EXT_disjoint_timer_query"_s && !isDriverWorkaroundDisabled("firefox-fake-disjoint-timer-query-webgl2"_s)) { _extensionStatus.set(Extensions::EXT::disjoint_timer_query_webgl2::Index, true); } } diff --git a/src/Magnum/GL/Test/ContextGLTest.cpp b/src/Magnum/GL/Test/ContextGLTest.cpp index 29bda212a..c51635338 100644 --- a/src/Magnum/GL/Test/ContextGLTest.cpp +++ b/src/Magnum/GL/Test/ContextGLTest.cpp @@ -24,6 +24,8 @@ */ #include +#include +#include #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" @@ -39,6 +41,8 @@ namespace Magnum { namespace GL { namespace Test { namespace { struct ContextGLTest: OpenGLTester { explicit ContextGLTest(); + void stringFlags(); + void makeCurrent(); #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -56,6 +60,8 @@ struct ContextGLTest: OpenGLTester { ContextGLTest::ContextGLTest() { addTests({ + &ContextGLTest::stringFlags, + &ContextGLTest::makeCurrent, #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -71,6 +77,45 @@ ContextGLTest::ContextGLTest() { &ContextGLTest::isExtensionDisabled}); } +void ContextGLTest::stringFlags() { + Context& context = Context::current(); + + CORRADE_VERIFY(!context.vendorString().isEmpty()); + CORRADE_COMPARE(context.vendorString().flags(), Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + + CORRADE_VERIFY(!context.rendererString().isEmpty()); + CORRADE_COMPARE(context.rendererString().flags(), Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + + CORRADE_VERIFY(!context.versionString().isEmpty()); + CORRADE_COMPARE(context.versionString().flags(), Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + + CORRADE_VERIFY(!context.shadingLanguageVersionString().isEmpty()); + CORRADE_COMPARE(context.shadingLanguageVersionString().flags(), Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + + for(Containers::StringView languageVersion: context.shadingLanguageVersionStrings()) { + /* One of these might be empty */ + CORRADE_COMPARE(languageVersion.flags(), Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + } + + for(Containers::StringView extension: context.extensionStrings()) { + CORRADE_VERIFY(!extension.isEmpty()); + + /* On GL 2.1 and GLES2 the extensions are split from a long string and + thus aren't all null-terminated, only the last one */ + #ifndef MAGNUM_TARGET_GLES + if(context.isVersionSupported(Version::GL300)) + #else + if(context.isVersionSupported(Version::GLES300)) + #endif + { + CORRADE_COMPARE(extension.flags(), Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + } else { + CORRADE_COMPARE_AS(extension.flags(), Containers::StringViewFlag::Global, + TestSuite::Compare::GreaterOrEqual); + } + } +} + void ContextGLTest::makeCurrent() { CORRADE_VERIFY(Context::hasCurrent()); @@ -166,7 +211,7 @@ void ContextGLTest::isExtensionSupported() { CORRADE_SKIP(Extensions::ARB::explicit_attrib_location::string() + std::string(" extension should be supported, can't test")); /* Test that we have proper extension list parser */ - std::vector extensions = Context::current().extensionStrings(); + Containers::Array extensions = Context::current().extensionStrings(); CORRADE_VERIFY(std::find(extensions.begin(), extensions.end(), Extensions::EXT::texture_filter_anisotropic::string()) != extensions.end()); CORRADE_VERIFY(std::find(extensions.begin(), extensions.end(), diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index d744cb2bb..9226476bc 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -27,6 +27,7 @@ #include "WindowlessGlxApplication.h" #include +#include #include #include diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index e697fb442..0d9c2cbb5 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -26,6 +26,7 @@ #include "WindowlessWglApplication.h" #include +#include #include #include diff --git a/src/Magnum/Platform/gl-info.cpp b/src/Magnum/Platform/gl-info.cpp index b354cfa10..28e205a59 100644 --- a/src/Magnum/Platform/gl-info.cpp +++ b/src/Magnum/Platform/gl-info.cpp @@ -195,6 +195,8 @@ class MagnumInfo: public Platform::WindowlessApplication { int exec() override { return 0; } }; +using namespace Containers::Literals; + MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { Utility::Arguments args; args.addBooleanOption('s', "short").setHelp("short", "display just essential info and exit") @@ -359,7 +361,7 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat Debug{} << "Detected driver:" << c.detectedDriver(); Debug{} << "Supported GLSL versions:"; - Debug{} << " " << Utility::String::joinWithoutEmptyParts(c.shadingLanguageVersionStrings(), ", "); + Debug{} << " " << ", "_s.joinWithoutEmptyParts(c.shadingLanguageVersionStrings()); if(args.isSet("extension-strings")) { Debug{} << "Extension strings:" << Debug::newline diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index 90ad208ae..1e074b21a 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1246,13 +1247,13 @@ void PhongGLTest::renderShininess() { "ARM Mali has a much larger ring for the overflown shininess when it's exactly 0."); #endif #ifndef MAGNUM_TARGET_WEBGL - CORRADE_EXPECT_FAIL_IF(data.shininess == 0.0f && (GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::Mesa) && GL::Context::current().rendererString().find("AMD") != std::string::npos, + CORRADE_EXPECT_FAIL_IF(data.shininess == 0.0f && (GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::Mesa) && GL::Context::current().rendererString().contains("AMD"), "AMD Mesa drivers have a much larger ring for the overflown shininess when it's exactly 0."); - CORRADE_EXPECT_FAIL_IF(data.shininess <= 0.0011f && (GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::Mesa) && GL::Context::current().rendererString().find("llvmpipe") != std::string::npos, + CORRADE_EXPECT_FAIL_IF(data.shininess <= 0.0011f && (GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::Mesa) && GL::Context::current().rendererString().contains("llvmpipe"), "Mesa llvmpipe drivers have a much larger ring for the overflown shininess."); #endif #if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS) - CORRADE_EXPECT_FAIL_IF(data.shininess == 0.0f && GL::Context::current().rendererString().find("AMD") != std::string::npos, + CORRADE_EXPECT_FAIL_IF(data.shininess == 0.0f && GL::Context::current().rendererString().contains("AMD"), "AMD on macOS has a much larger ring for the overflown shininess when it's exactly 0."); #endif CORRADE_COMPARE_WITH( @@ -1268,10 +1269,10 @@ void PhongGLTest::renderShininess() { || (data.shininess <= 0.0011f && (GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::SwiftShader)) #endif #ifndef MAGNUM_TARGET_WEBGL - || (data.shininess == 0.0f && (GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::Mesa) && GL::Context::current().rendererString().find("AMD") != std::string::npos) + || (data.shininess == 0.0f && (GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::Mesa) && GL::Context::current().rendererString().contains("AMD")) #endif #if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS) - || (data.shininess == 0.0f && GL::Context::current().rendererString().find("AMD") != std::string::npos) + || (data.shininess == 0.0f && GL::Context::current().rendererString().contains("AMD")) #endif #if defined(CORRADE_TARGET_ANDROID) && defined(MAGNUM_TARGET_GLES2) || (data.shininess == 0.0f && (GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali)) diff --git a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp index 2d1c67cba..76fffe8e7 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp +++ b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp @@ -33,6 +33,7 @@ #ifdef MAGNUM_PLATFORM_USE_EGL #include #include +#include #include "Magnum/GL/Context.h" #endif diff --git a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp.template b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp.template index e0ccb0182..6fe6080e7 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp.template +++ b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp.template @@ -34,6 +34,7 @@ #ifdef MAGNUM_PLATFORM_USE_EGL #include #include +#include #include "Magnum/GL/Context.h" #endif From 32a7adefed8678a927d35056acaab4c1928eac76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Feb 2021 17:57:27 +0100 Subject: [PATCH 010/161] GL: use StringView literals for all workaround names. These are in most cases the only strings that are used, and I don't think having to call std::strlen() for each of them is a good idea if we don't need to. --- src/Magnum/GL/Implementation/BufferState.cpp | 10 ++++--- src/Magnum/GL/Implementation/ContextState.cpp | 4 ++- .../GL/Implementation/FramebufferState.cpp | 16 +++++----- src/Magnum/GL/Implementation/MeshState.cpp | 8 +++-- src/Magnum/GL/Implementation/QueryState.cpp | 8 +++-- .../GL/Implementation/RendererState.cpp | 4 ++- .../GL/Implementation/ShaderProgramState.cpp | 8 +++-- src/Magnum/GL/Implementation/ShaderState.cpp | 6 ++-- src/Magnum/GL/Implementation/TextureState.cpp | 30 ++++++++++--------- src/Magnum/Platform/GlfwApplication.cpp | 4 ++- src/Magnum/Platform/Sdl2Application.cpp | 4 ++- .../Platform/WindowlessEglApplication.cpp | 10 ++++--- .../Platform/WindowlessGlxApplication.cpp | 4 ++- .../Platform/WindowlessWglApplication.cpp | 4 ++- .../OpenGL/GL/flextGLPlatform.cpp | 4 ++- .../OpenGL/GL/flextGLPlatform.cpp.template | 4 ++- 16 files changed, 80 insertions(+), 48 deletions(-) diff --git a/src/Magnum/GL/Implementation/BufferState.cpp b/src/Magnum/GL/Implementation/BufferState.cpp index c3b056da7..60a4f78df 100644 --- a/src/Magnum/GL/Implementation/BufferState.cpp +++ b/src/Magnum/GL/Implementation/BufferState.cpp @@ -34,6 +34,8 @@ namespace Magnum { namespace GL { namespace Implementation { +using namespace Containers::Literals; + const Buffer::TargetHint BufferState::targetForIndex[] = { Buffer::TargetHint::Array, Buffer::TargetHint::ElementArray, @@ -94,7 +96,7 @@ BufferState::BufferState(Context& context, std::vector& extensions) if(context.isExtensionSupported() #ifdef CORRADE_TARGET_WINDOWS && (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) || - context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-buffer-dsa")) + context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-buffer-dsa"_s)) #endif ) { extensions.emplace_back(Extensions::ARB::direct_state_access::string()); @@ -167,7 +169,7 @@ BufferState::BufferState(Context& context, std::vector& extensions) #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported() && (context.detectedDriver() & Context::DetectedDriver::Svga3D) && - !context.isDriverWorkaroundDisabled("svga3d-broken-dsa-bufferdata")) + !context.isDriverWorkaroundDisabled("svga3d-broken-dsa-bufferdata"_s)) { dataImplementation = &Buffer::dataImplementationDefault; } @@ -175,7 +177,7 @@ BufferState::BufferState(Context& context, std::vector& extensions) #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) if((context.detectedDriver() & Context::DetectedDriver::SwiftShader) && - !context.isDriverWorkaroundDisabled("swiftshader-broken-xfb-buffer-binding-target")) + !context.isDriverWorkaroundDisabled("swiftshader-broken-xfb-buffer-binding-target"_s)) { setTargetHintImplementation = &Buffer::setTargetHintImplementationSwiftShader; } else @@ -185,7 +187,7 @@ BufferState::BufferState(Context& context, std::vector& extensions) } #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) - if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify")) { + if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify"_s)) { dataImplementation = &Buffer::dataImplementationApple; subDataImplementation = &Buffer::subDataImplementationApple; mapImplementation = &Buffer::mapImplementationApple; diff --git a/src/Magnum/GL/Implementation/ContextState.cpp b/src/Magnum/GL/Implementation/ContextState.cpp index da6478547..e9fae46a5 100644 --- a/src/Magnum/GL/Implementation/ContextState.cpp +++ b/src/Magnum/GL/Implementation/ContextState.cpp @@ -31,10 +31,12 @@ namespace Magnum { namespace GL { namespace Implementation { +using namespace Containers::Literals; + ContextState::ContextState(Context& context, std::vector&) { #ifndef MAGNUM_TARGET_GLES if((context.detectedDriver() & Context::DetectedDriver::NVidia) && - !context.isDriverWorkaroundDisabled("nv-zero-context-profile-mask")) + !context.isDriverWorkaroundDisabled("nv-zero-context-profile-mask"_s)) { isCoreProfileImplementation = &Context::isCoreProfileImplementationNV; } else isCoreProfileImplementation = &Context::isCoreProfileImplementationDefault; diff --git a/src/Magnum/GL/Implementation/FramebufferState.cpp b/src/Magnum/GL/Implementation/FramebufferState.cpp index 1f07ca2e5..bae28c63e 100644 --- a/src/Magnum/GL/Implementation/FramebufferState.cpp +++ b/src/Magnum/GL/Implementation/FramebufferState.cpp @@ -35,6 +35,8 @@ namespace Magnum { namespace GL { namespace Implementation { +using namespace Containers::Literals; + constexpr const Range2Di FramebufferState::DisengagedViewport; FramebufferState::FramebufferState(Context& context, std::vector& extensions): readBinding{0}, drawBinding{0}, renderbufferBinding{0}, maxDrawBuffers{0}, maxColorAttachments{0}, maxRenderbufferSize{0}, @@ -131,10 +133,10 @@ FramebufferState::FramebufferState(Context& context, std::vector& e #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { #ifdef CORRADE_TARGET_WINDOWS - if(context.detectedDriver() & Context::DetectedDriver::IntelWindows && !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps")) { + if(context.detectedDriver() & Context::DetectedDriver::IntelWindows && !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps"_s)) { copySubCubeMapImplementation = &AbstractFramebuffer::copySub2DImplementationDefault; textureCubeMapImplementation = &Framebuffer::texture2DImplementationDefault; - } else if(context.detectedDriver() & Context::DetectedDriver::Amd && !context.isDriverWorkaroundDisabled("amd-windows-broken-dsa-cubemap-copy")) { + } else if(context.detectedDriver() & Context::DetectedDriver::Amd && !context.isDriverWorkaroundDisabled("amd-windows-broken-dsa-cubemap-copy"_s)) { copySubCubeMapImplementation = &AbstractFramebuffer::copySub2DImplementationDefault; /* Cube map attachment is not broken */ textureCubeMapImplementation = &Framebuffer::texture2DImplementationDSA; @@ -160,7 +162,7 @@ FramebufferState::FramebufferState(Context& context, std::vector& e if(context.isExtensionSupported() #ifdef CORRADE_TARGET_WINDOWS && (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) || - context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-layered-cubemap-array-framebuffer-attachment")) + context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-layered-cubemap-array-framebuffer-attachment"_s)) #endif ) { /* Extension name added above */ @@ -179,7 +181,7 @@ FramebufferState::FramebufferState(Context& context, std::vector& e if(context.isExtensionSupported() #ifdef CORRADE_TARGET_WINDOWS && (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) || - context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-framebuffer-clear")) + context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-framebuffer-clear"_s)) #endif ) { /* Extension name added above */ @@ -288,15 +290,15 @@ FramebufferState::FramebufferState(Context& context, std::vector& e if(context.isVersionSupported(Version::GL450) #ifdef CORRADE_TARGET_WINDOWS && !((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && - !context.isDriverWorkaroundDisabled("intel-windows-implementation-color-read-format-completely-broken")) + !context.isDriverWorkaroundDisabled("intel-windows-implementation-color-read-format-completely-broken"_s)) #endif ) { if(context.isExtensionSupported() - && !((context.detectedDriver() & Context::DetectedDriver::NVidia) && !context.isDriverWorkaroundDisabled("nv-implementation-color-read-format-dsa-broken")) + && !((context.detectedDriver() & Context::DetectedDriver::NVidia) && !context.isDriverWorkaroundDisabled("nv-implementation-color-read-format-dsa-broken"_s)) ) { /* DSA extension added above */ - if((context.detectedDriver() & Context::DetectedDriver::Mesa) && !context.isDriverWorkaroundDisabled("mesa-implementation-color-read-format-dsa-explicit-binding")) + if((context.detectedDriver() & Context::DetectedDriver::Mesa) && !context.isDriverWorkaroundDisabled("mesa-implementation-color-read-format-dsa-explicit-binding"_s)) implementationColorReadFormatTypeImplementation = &AbstractFramebuffer::implementationColorReadFormatTypeImplementationFramebufferDSAMesa; else implementationColorReadFormatTypeImplementation = &AbstractFramebuffer::implementationColorReadFormatTypeImplementationFramebufferDSA; } else { diff --git a/src/Magnum/GL/Implementation/MeshState.cpp b/src/Magnum/GL/Implementation/MeshState.cpp index c5320a2ee..cd44de651 100644 --- a/src/Magnum/GL/Implementation/MeshState.cpp +++ b/src/Magnum/GL/Implementation/MeshState.cpp @@ -35,6 +35,8 @@ namespace Magnum { namespace GL { namespace Implementation { +using namespace Containers::Literals; + MeshState::MeshState(Context& context, ContextState& contextState, std::vector& extensions): currentVAO(0) #ifndef MAGNUM_TARGET_GLES2 , maxElementIndex{0}, maxElementsIndices{0}, maxElementsVertices{0} @@ -59,7 +61,7 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector() #ifdef CORRADE_TARGET_WINDOWS && (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) || - context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-vao-dsa")) + context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-vao-dsa"_s)) #endif ) { extensions.emplace_back(Extensions::ARB::direct_state_access::string()); @@ -67,7 +69,7 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector() #ifdef CORRADE_TARGET_WINDOWS && (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) || - context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-vao-dsa")) + context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-vao-dsa"_s)) #endif ) vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationVAODSA; diff --git a/src/Magnum/GL/Implementation/QueryState.cpp b/src/Magnum/GL/Implementation/QueryState.cpp index b2c4606a5..41fb3168d 100644 --- a/src/Magnum/GL/Implementation/QueryState.cpp +++ b/src/Magnum/GL/Implementation/QueryState.cpp @@ -33,19 +33,21 @@ namespace Magnum { namespace GL { namespace Implementation { +using namespace Containers::Literals; + QueryState::QueryState(Context& context, std::vector& extensions) { /* Create implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { #ifdef CORRADE_TARGET_WINDOWS - if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-indexed-queries")) { + if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-indexed-queries"_s)) { createImplementation = &AbstractQuery::createImplementationDefault; - } else if((context.detectedDriver() & Context::DetectedDriver::Amd) && !context.isDriverWorkaroundDisabled("amd-windows-dsa-createquery-except-xfb-overflow")) { + } else if((context.detectedDriver() & Context::DetectedDriver::Amd) && !context.isDriverWorkaroundDisabled("amd-windows-dsa-createquery-except-xfb-overflow"_s)) { extensions.emplace_back(Extensions::ARB::direct_state_access::string()); createImplementation = &AbstractQuery::createImplementationDSAExceptXfbOverflow; } else #endif - if((context.detectedDriver() & Context::DetectedDriver::Mesa) && !context.isDriverWorkaroundDisabled("mesa-dsa-createquery-except-pipeline-stats")) { + if((context.detectedDriver() & Context::DetectedDriver::Mesa) && !context.isDriverWorkaroundDisabled("mesa-dsa-createquery-except-pipeline-stats"_s)) { extensions.emplace_back(Extensions::ARB::direct_state_access::string()); createImplementation = &AbstractQuery::createImplementationDSAExceptPipelineStats; } else { diff --git a/src/Magnum/GL/Implementation/RendererState.cpp b/src/Magnum/GL/Implementation/RendererState.cpp index 1e909a992..6ebd3f909 100644 --- a/src/Magnum/GL/Implementation/RendererState.cpp +++ b/src/Magnum/GL/Implementation/RendererState.cpp @@ -33,6 +33,8 @@ namespace Magnum { namespace GL { namespace Implementation { +using namespace Containers::Literals; + RendererState::RendererState(Context& context, ContextState& contextState, std::vector& extensions) #ifndef MAGNUM_TARGET_WEBGL : resetNotificationStrategy() @@ -90,7 +92,7 @@ RendererState::RendererState(Context& context, ContextState& contextState, std:: #ifndef MAGNUM_TARGET_GLES if((context.detectedDriver() & Context::DetectedDriver::Mesa) && (context.flags() & Context::Flag::ForwardCompatible) && - !context.isDriverWorkaroundDisabled("mesa-forward-compatible-line-width-range")) + !context.isDriverWorkaroundDisabled("mesa-forward-compatible-line-width-range"_s)) lineWidthRangeImplementation = &Renderer::lineWidthRangeImplementationMesaForwardCompatible; else #endif diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.cpp b/src/Magnum/GL/Implementation/ShaderProgramState.cpp index 1ca259ff8..e22fc5190 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/GL/Implementation/ShaderProgramState.cpp @@ -35,6 +35,8 @@ namespace Magnum { namespace GL { namespace Implementation { +using namespace Containers::Literals; + ShaderProgramState::ShaderProgramState(Context& context, std::vector& extensions): current(0), maxVertexAttributes(0) #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_WEBGL @@ -52,7 +54,7 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector&): maxVertexOutputComponents{}, maxFragmentInputComponents{}, #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -49,7 +51,7 @@ ShaderState::ShaderState(Context& context, std::vector&): #endif { #if defined(CORRADE_TARGET_EMSCRIPTEN) && defined(__EMSCRIPTEN_PTHREADS__) - if(!context.isDriverWorkaroundDisabled("emscripten-pthreads-broken-unicode-shader-sources")) { + if(!context.isDriverWorkaroundDisabled("emscripten-pthreads-broken-unicode-shader-sources"_s)) { addSourceImplementation = &Shader::addSourceImplementationEmscriptenPthread; } else #endif @@ -58,7 +60,7 @@ ShaderState::ShaderState(Context& context, std::vector&): } #if defined(CORRADE_TARGET_WINDOWS) && !defined(MAGNUM_TARGET_GLES) - if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && !context.isDriverWorkaroundDisabled("intel-windows-chatty-shader-compiler")) { + if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && !context.isDriverWorkaroundDisabled("intel-windows-chatty-shader-compiler"_s)) { cleanLogImplementation = &Shader::cleanLogImplementationIntelWindows; } else #endif diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index a0502c123..f96b2987a 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -41,6 +41,8 @@ namespace Magnum { namespace GL { namespace Implementation { +using namespace Containers::Literals; + TextureState::TextureState(Context& context, std::vector& extensions): maxSize{}, #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) max3DSize{}, @@ -83,7 +85,7 @@ TextureState::TextureState(Context& context, std::vector& extension #ifdef CORRADE_TARGET_WINDOWS if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && - !context.isDriverWorkaroundDisabled("intel-windows-half-baked-dsa-texture-bind")) + !context.isDriverWorkaroundDisabled("intel-windows-half-baked-dsa-texture-bind"_s)) { unbindImplementation = &AbstractTexture::unbindImplementationDefault; bindImplementation = &AbstractTexture::bindImplementationDSAIntelWindows; @@ -185,11 +187,11 @@ TextureState::TextureState(Context& context, std::vector& extension if(context.isExtensionSupported()) { #ifdef CORRADE_TARGET_WINDOWS - if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps")) { + if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps"_s)) { getCubeLevelParameterivImplementation = &CubeMapTexture::getLevelParameterImplementationDefault; cubeSubImageImplementation = &CubeMapTexture::subImageImplementationDefault; cubeCompressedSubImageImplementation = &CubeMapTexture::compressedSubImageImplementationDefault; - } else if((context.detectedDriver() & Context::DetectedDriver::Amd) && !context.isDriverWorkaroundDisabled("amd-windows-cubemap-image3d-slice-by-slice")) { + } else if((context.detectedDriver() & Context::DetectedDriver::Amd) && !context.isDriverWorkaroundDisabled("amd-windows-cubemap-image3d-slice-by-slice"_s)) { /* This one is not broken, but the others are */ getCubeLevelParameterivImplementation = &CubeMapTexture::getLevelParameterImplementationDSA; cubeSubImageImplementation = &CubeMapTexture::subImageImplementationDefault; @@ -257,14 +259,14 @@ TextureState::TextureState(Context& context, std::vector& extension /* Compressed cubemap image size query implementation (extensions added above) */ if((context.detectedDriver() & Context::DetectedDriver::NVidia) && - !context.isDriverWorkaroundDisabled("nv-cubemap-inconsistent-compressed-image-size")) { + !context.isDriverWorkaroundDisabled("nv-cubemap-inconsistent-compressed-image-size"_s)) { if(context.isExtensionSupported()) getCubeLevelCompressedImageSizeImplementation = &CubeMapTexture::getLevelCompressedImageSizeImplementationDSANonImmutableWorkaround; else getCubeLevelCompressedImageSizeImplementation = &CubeMapTexture::getLevelCompressedImageSizeImplementationDefaultImmutableWorkaround; } else if(context.isExtensionSupported() #ifdef CORRADE_TARGET_WINDOWS && (!(context.detectedDriver() & Context::DetectedDriver::IntelWindows) || - context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps")) + context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps"_s)) #endif ) { getCubeLevelCompressedImageSizeImplementation = &CubeMapTexture::getLevelCompressedImageSizeImplementationDSA; @@ -308,7 +310,7 @@ TextureState::TextureState(Context& context, std::vector& extension above) */ if((context.detectedDriver() & Context::DetectedDriver::NVidia) && context.isExtensionSupported() && - !context.isDriverWorkaroundDisabled("nv-cubemap-broken-full-compressed-image-query")) + !context.isDriverWorkaroundDisabled("nv-cubemap-broken-full-compressed-image-query"_s)) getFullCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSASingleSliceWorkaround; else getFullCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSA; @@ -318,11 +320,11 @@ TextureState::TextureState(Context& context, std::vector& extension linux as well, test */ if((context.detectedDriver() & Context::DetectedDriver::Amd) && context.isExtensionSupported() && - !context.isDriverWorkaroundDisabled("amd-windows-cubemap-image3d-slice-by-slice")) + !context.isDriverWorkaroundDisabled("amd-windows-cubemap-image3d-slice-by-slice"_s)) getFullCubeImageImplementation = &CubeMapTexture::getImageImplementationDSAAmdSliceBySlice; else if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && context.isExtensionSupported() && - !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps")) + !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps"_s)) getFullCubeImageImplementation = &CubeMapTexture::getImageImplementationSliceBySlice; else #endif @@ -426,7 +428,7 @@ TextureState::TextureState(Context& context, std::vector& extension #ifndef MAGNUM_TARGET_GLES /* NVidia workaround for compressed block data size implementation */ if((context.detectedDriver() & Context::DetectedDriver::NVidia) && - !context.isDriverWorkaroundDisabled("nv-compressed-block-size-in-bits")) + !context.isDriverWorkaroundDisabled("nv-compressed-block-size-in-bits"_s)) compressedBlockDataSizeImplementation = &AbstractTexture::compressedBlockDataSizeImplementationBitsWorkaround; else compressedBlockDataSizeImplementation = &AbstractTexture::compressedBlockDataSizeImplementationDefault; @@ -436,7 +438,7 @@ TextureState::TextureState(Context& context, std::vector& extension /* SVGA3D workaround for array / 3D / cube map texture upload. Overrides the DSA / non-DSA function pointers set above. */ if((context.detectedDriver() & Context::DetectedDriver::Svga3D) && - !context.isDriverWorkaroundDisabled("svga3d-texture-upload-slice-by-slice")) { + !context.isDriverWorkaroundDisabled("svga3d-texture-upload-slice-by-slice"_s)) { #ifndef MAGNUM_TARGET_GLES image2DImplementation = &AbstractTexture::imageImplementationSvga3DSliceBySlice; #endif @@ -470,21 +472,21 @@ TextureState::TextureState(Context& context, std::vector& extension /* SVGA3D and Intel workaround for cube map texture upload. Overrides the DSA / non-DSA function pointers set above. */ if((context.detectedDriver() & Context::DetectedDriver::Svga3D) && - !context.isDriverWorkaroundDisabled("svga3d-texture-upload-slice-by-slice")) { + !context.isDriverWorkaroundDisabled("svga3d-texture-upload-slice-by-slice"_s)) { if(context.isExtensionSupported()) { cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationDSASliceBySlice; } else { cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationSliceBySlice; } } else if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && - !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps")) { + !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps"_s)) { cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationSliceBySlice; } #ifdef CORRADE_TARGET_WINDOWS /** @todo those *might* be happening with the proprietary AMD driver on linux as well, test */ else if((context.detectedDriver() & Context::DetectedDriver::Amd) && - !context.isDriverWorkaroundDisabled("amd-windows-cubemap-image3d-slice-by-slice")) { + !context.isDriverWorkaroundDisabled("amd-windows-cubemap-image3d-slice-by-slice"_s)) { /* DSA version is broken (non-zero Z offset not allowed), need to emulate using classic APIs */ cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationSliceBySlice; @@ -504,7 +506,7 @@ TextureState::TextureState(Context& context, std::vector& extension bindings = Containers::Array>{Containers::ValueInit, std::size_t(maxTextureUnits)}; #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) - if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify")) { + if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify"_s)) { CORRADE_INTERNAL_ASSERT(std::size_t(maxTextureUnits) <= decltype(bufferTextureBound)::Size); /* Assume ARB_multi_bind is not supported, otherwise we'd need to implement the workaround also for bindMultiImplementation */ diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 3115e49c2..0fcd147c7 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -49,6 +49,8 @@ namespace Magnum { namespace Platform { +using namespace Containers::Literals; + #ifdef GLFW_TRUE /* The docs say that it's the same, verify that just in case */ static_assert(GLFW_TRUE == true && GLFW_FALSE == false, "GLFW does not have sane bool values"); @@ -532,7 +534,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf std::strncmp(vendorString, intelVendorString, sizeof(intelVendorString)) == 0 || #endif std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) - && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context")) + && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s)) #endif )) { /* Don't print any warning when doing the workaround, because the bug diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index aed91cacb..ccec3f2d3 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -69,6 +69,8 @@ namespace Magnum { namespace Platform { +using namespace Containers::Literals; + namespace { /* @@ -560,7 +562,7 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf std::strncmp(vendorString, intelVendorString, sizeof(intelVendorString)) == 0 || #endif std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) - && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context")) + && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s)) #endif )) { /* Don't print any warning when doing the workaround, because the bug diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 6a6462e47..41b2e5faa 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -72,6 +72,8 @@ typedef void (APIENTRY *EGLDEBUGPROCKHR)(EGLenum error, const char* command, EGL namespace Magnum { namespace Platform { +using namespace Containers::Literals; + #ifndef MAGNUM_TARGET_WEBGL namespace { @@ -190,7 +192,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G well-behaved driver versions, eglQueryDeviceAttribEXT() returns false instead of segfaulting. */ const char* const eglExtensions = eglQueryDeviceStringEXT(devices[selectedDevice], EGL_EXTENSIONS); - if(eglGetError() == EGL_BAD_DEVICE_EXT && !magnumContext->isDriverWorkaroundDisabled("nv-egl-crashy-query-device-attrib")) + if(eglGetError() == EGL_BAD_DEVICE_EXT && !magnumContext->isDriverWorkaroundDisabled("nv-egl-crashy-query-device-attrib"_s)) continue; if(magnumContext && (magnumContext->internalFlags() >= GL::Context::InternalFlag::DisplayVerboseInitializationLog)) @@ -344,7 +346,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G a zero value, so erase these. It also doesn't handle them as correct flags, but instead checks for the whole value, so a combination won't work either: https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L8104 */ - if(!configuration.flags() && version && std::strstr(version, "SwiftShader") != nullptr && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"))) { + if(!configuration.flags() && version && std::strstr(version, "SwiftShader") != nullptr && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) { auto& contextFlags = attributes[Containers::arraySize(attributes) - 3]; CORRADE_INTERNAL_ASSERT(contextFlags == EGL_CONTEXT_FLAGS_KHR); contextFlags = EGL_NONE; @@ -399,7 +401,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G strncmp() */ if(vendorString && (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && - (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"))) + (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) { /* Destroy the core context and create a compatibility one */ eglDestroyContext(_display, _context); @@ -430,7 +432,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) /* SwiftShader 3.3.0.1 needs some pbuffer, otherwise it crashes somewhere deep inside when making the context current */ - if(version && std::strstr(version, "SwiftShader") != nullptr && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-egl-context-needs-pbuffer"))) { + if(version && std::strstr(version, "SwiftShader") != nullptr && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-egl-context-needs-pbuffer"_s))) { EGLint surfaceAttributes[] = { EGL_WIDTH, 32, EGL_HEIGHT, 32, diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index 9226476bc..e010ef495 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -39,6 +39,8 @@ namespace { enum { None = 0, Success = 0 }; } namespace Magnum { namespace Platform { +using namespace Containers::Literals; + namespace { /* @@ -188,7 +190,7 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura strncmp() */ if(vendorString && (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && - (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"))) + (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) { /* Destroy the core context and create a compatibility one */ glXDestroyContext(_display, _context); diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 0d9c2cbb5..2dd1bbc29 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -46,6 +46,8 @@ namespace Magnum { namespace Platform { +using namespace Containers::Literals; + WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, GLContext* const magnumContext) { /* Register the window class (if not yet done) */ WNDCLASSW wc; @@ -188,7 +190,7 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G if(vendorString && (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || std::strncmp(vendorString, intelVendorString, sizeof(intelVendorString)) == 0 || std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && - (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"))) + (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) { /* Destroy the core context and create a compatibility one */ wglDeleteContext(_context); diff --git a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp index 76fffe8e7..89a9b0f05 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp +++ b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp @@ -42,12 +42,14 @@ void flextGLInit(Magnum::GL::Context& context) { #ifdef MAGNUM_PLATFORM_USE_EGL { + using namespace Corrade::Containers::Literals; + /* EGL contexts on NVidia 390 drivers don't have correct statically linked GL 1.0 and 1.1 functions (such as glGetString()) and one has to retrieve them explicitly using eglGetProcAddress(). */ EGLDisplay display = eglGetCurrentDisplay(); const char* vendor = eglQueryString(display, EGL_VENDOR); - if(std::strcmp(vendor, "NVIDIA") == 0 && !context.isDriverWorkaroundDisabled("nv-egl-incorrect-gl11-function-pointers")) { + if(std::strcmp(vendor, "NVIDIA") == 0 && !context.isDriverWorkaroundDisabled("nv-egl-incorrect-gl11-function-pointers"_s)) { /* GL_VERSION_1_0 */ flextGL.BlendFunc = reinterpret_cast(loader.load("glBlendFunc")); diff --git a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp.template b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp.template index 6fe6080e7..78f9cb082 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp.template +++ b/src/MagnumExternal/OpenGL/GL/flextGLPlatform.cpp.template @@ -43,12 +43,14 @@ void flextGLInit(Magnum::GL::Context& context) { #ifdef MAGNUM_PLATFORM_USE_EGL { + using namespace Corrade::Containers::Literals; + /* EGL contexts on NVidia 390 drivers don't have correct statically linked GL 1.0 and 1.1 functions (such as glGetString()) and one has to retrieve them explicitly using eglGetProcAddress(). */ EGLDisplay display = eglGetCurrentDisplay(); const char* vendor = eglQueryString(display, EGL_VENDOR); - if(std::strcmp(vendor, "NVIDIA") == 0 && !context.isDriverWorkaroundDisabled("nv-egl-incorrect-gl11-function-pointers")) { + if(std::strcmp(vendor, "NVIDIA") == 0 && !context.isDriverWorkaroundDisabled("nv-egl-incorrect-gl11-function-pointers"_s)) { @for category,funcs in functions: @if funcs and category in ['VERSION_1_0', 'VERSION_1_1']: From e96996ea0169c6df860ff967ebb242da746825c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Feb 2021 20:12:24 +0100 Subject: [PATCH 011/161] GL: avoid populating and sorting (!!) a vector of strings for exts. Ew. At first I tried to just port a growable Array of StringViews (which would already save quite a lot), but then I realized I have a clear upper bound on the extensions and so can use a "counting sort" without having to deduplicate anything after. After the previous (rather minimal) reduction by the Context cleanup, this reduces the size of magnum-gl-info.wasm from 245 to 237 kB. Quite significant, I'd say! --- src/Magnum/GL/Context.h | 11 --- src/Magnum/GL/GL.h | 16 ++++ src/Magnum/GL/Implementation/BufferState.cpp | 11 ++- src/Magnum/GL/Implementation/BufferState.h | 4 +- src/Magnum/GL/Implementation/ContextState.cpp | 2 +- src/Magnum/GL/Implementation/ContextState.h | 6 +- src/Magnum/GL/Implementation/DebugState.cpp | 17 ++-- src/Magnum/GL/Implementation/DebugState.h | 5 +- .../GL/Implementation/FramebufferState.cpp | 83 ++++++++++++------ .../GL/Implementation/FramebufferState.h | 5 +- src/Magnum/GL/Implementation/MeshState.cpp | 85 +++++++++++++------ src/Magnum/GL/Implementation/MeshState.h | 5 +- src/Magnum/GL/Implementation/QueryState.cpp | 14 ++- src/Magnum/GL/Implementation/QueryState.h | 6 +- .../GL/Implementation/RendererState.cpp | 21 +++-- src/Magnum/GL/Implementation/RendererState.h | 5 +- .../GL/Implementation/ShaderProgramState.cpp | 8 +- .../GL/Implementation/ShaderProgramState.h | 6 +- src/Magnum/GL/Implementation/ShaderState.cpp | 2 +- src/Magnum/GL/Implementation/ShaderState.h | 6 +- src/Magnum/GL/Implementation/State.cpp | 24 ++---- src/Magnum/GL/Implementation/TextureState.cpp | 47 ++++++---- src/Magnum/GL/Implementation/TextureState.h | 4 +- .../Implementation/TransformFeedbackState.cpp | 5 +- .../Implementation/TransformFeedbackState.h | 7 +- 25 files changed, 242 insertions(+), 163 deletions(-) diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 8b42a55ef..54c2e7f5e 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -57,17 +57,6 @@ namespace GL { namespace Implementation { struct ContextState; struct State; - - enum: std::size_t { - ExtensionCount = - #ifndef MAGNUM_TARGET_GLES - 192 - #elif !defined(MAGNUM_TARGET_WEBGL) - 160 - #else - 48 - #endif - }; } /** diff --git a/src/Magnum/GL/GL.h b/src/Magnum/GL/GL.h index 132f89e22..6371880c6 100644 --- a/src/Magnum/GL/GL.h +++ b/src/Magnum/GL/GL.h @@ -29,6 +29,8 @@ * @brief Forward declarations for the @ref Magnum::GL namespace */ +#include + #include "Magnum/Types.h" #ifndef DOXYGEN_GENERATING_OUTPUT @@ -40,6 +42,20 @@ typedef unsigned int GLuint; /* Needed by Implementation/State.h */ namespace Magnum { namespace GL { #ifndef DOXYGEN_GENERATING_OUTPUT +namespace Implementation { + /* Needed by Context as well as all Implementation::*State classes */ + enum: std::size_t { + ExtensionCount = + #ifndef MAGNUM_TARGET_GLES + 192 + #elif !defined(MAGNUM_TARGET_WEBGL) + 160 + #else + 48 + #endif + }; +} + /* FramebufferClear[Mask], FramebufferBlit[Mask], FramebufferBlitFilter, FramebufferTarget enums used only directly with framebuffer instance */ class AbstractFramebuffer; diff --git a/src/Magnum/GL/Implementation/BufferState.cpp b/src/Magnum/GL/Implementation/BufferState.cpp index 60a4f78df..54494b552 100644 --- a/src/Magnum/GL/Implementation/BufferState.cpp +++ b/src/Magnum/GL/Implementation/BufferState.cpp @@ -80,7 +80,7 @@ std::size_t BufferState::indexForTarget(Buffer::TargetHint target) { CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } -BufferState::BufferState(Context& context, std::vector& extensions): bindings() +BufferState::BufferState(Context& context, Containers::StaticArrayView extensions): bindings() #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES , minMapAlignment(0) @@ -99,7 +99,8 @@ BufferState::BufferState(Context& context, std::vector& extensions) context.isDriverWorkaroundDisabled("intel-windows-crazy-broken-buffer-dsa"_s)) #endif ) { - extensions.emplace_back(Extensions::ARB::direct_state_access::string()); + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); createImplementation = &Buffer::createImplementationDSA; copyImplementation = &Buffer::copyImplementationDSA; @@ -140,7 +141,8 @@ BufferState::BufferState(Context& context, std::vector& extensions) #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::invalidate_subdata::string()); + extensions[Extensions::ARB::invalidate_subdata::Index] = + Extensions::ARB::invalidate_subdata::string(); invalidateImplementation = &Buffer::invalidateImplementationARB; invalidateSubImplementation = &Buffer::invalidateSubImplementationARB; @@ -154,7 +156,8 @@ BufferState::BufferState(Context& context, std::vector& extensions) #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::multi_bind::string()); + extensions[Extensions::ARB::multi_bind::Index] = + Extensions::ARB::multi_bind::string(); bindBasesImplementation = &Buffer::bindImplementationMulti; bindRangesImplementation = &Buffer::bindImplementationMulti; diff --git a/src/Magnum/GL/Implementation/BufferState.h b/src/Magnum/GL/Implementation/BufferState.h index 1d7f55dd1..3c1dc5d0c 100644 --- a/src/Magnum/GL/Implementation/BufferState.h +++ b/src/Magnum/GL/Implementation/BufferState.h @@ -25,8 +25,6 @@ DEALINGS IN THE SOFTWARE. */ -#include - #include "Magnum/GL/Buffer.h" namespace Magnum { namespace GL { namespace Implementation { @@ -46,7 +44,7 @@ struct BufferState { static std::size_t indexForTarget(Buffer::TargetHint target); static const Buffer::TargetHint targetForIndex[TargetCount-1]; - explicit BufferState(Context& context, std::vector& extensions); + explicit BufferState(Context& context, Containers::StaticArrayView extensions); void reset(); diff --git a/src/Magnum/GL/Implementation/ContextState.cpp b/src/Magnum/GL/Implementation/ContextState.cpp index e9fae46a5..78a834a17 100644 --- a/src/Magnum/GL/Implementation/ContextState.cpp +++ b/src/Magnum/GL/Implementation/ContextState.cpp @@ -33,7 +33,7 @@ namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -ContextState::ContextState(Context& context, std::vector&) { +ContextState::ContextState(Context& context, Containers::StaticArrayView) { #ifndef MAGNUM_TARGET_GLES if((context.detectedDriver() & Context::DetectedDriver::NVidia) && !context.isDriverWorkaroundDisabled("nv-zero-context-profile-mask"_s)) diff --git a/src/Magnum/GL/Implementation/ContextState.h b/src/Magnum/GL/Implementation/ContextState.h index 63d1e13e1..f159a3231 100644 --- a/src/Magnum/GL/Implementation/ContextState.h +++ b/src/Magnum/GL/Implementation/ContextState.h @@ -25,9 +25,7 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include - +#include "Magnum/Magnum.h" #include "Magnum/GL/GL.h" #ifdef _MSC_VER @@ -40,7 +38,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct ContextState { - explicit ContextState(Context& context, std::vector& extensions); + explicit ContextState(Context& context, Containers::StaticArrayView extensions); #ifndef MAGNUM_TARGET_GLES enum class CoreProfile { diff --git a/src/Magnum/GL/Implementation/DebugState.cpp b/src/Magnum/GL/Implementation/DebugState.cpp index ed3f4301a..bf0aabb9a 100644 --- a/src/Magnum/GL/Implementation/DebugState.cpp +++ b/src/Magnum/GL/Implementation/DebugState.cpp @@ -31,7 +31,7 @@ namespace Magnum { namespace GL { namespace Implementation { -DebugState::DebugState(Context& context, std::vector& extensions): +DebugState::DebugState(Context& context, Containers::StaticArrayView extensions): maxLabelLength{0}, maxLoggedMessages{0}, maxMessageLength{0}, @@ -45,7 +45,8 @@ DebugState::DebugState(Context& context, std::vector& extensions): #endif { #ifndef MAGNUM_TARGET_GLES - extensions.emplace_back(Extensions::KHR::debug::string()); + extensions[Extensions::KHR::debug::Index] = + Extensions::KHR::debug::string(); #endif getLabelImplementation = &AbstractObject::getLabelImplementationKhrDesktopES32; @@ -60,7 +61,8 @@ DebugState::DebugState(Context& context, std::vector& extensions): #endif #ifdef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::KHR::debug::string()); + extensions[Extensions::KHR::debug::Index] = + Extensions::KHR::debug::string(); getLabelImplementation = &AbstractObject::getLabelImplementationKhrES; labelImplementation = &AbstractObject::labelImplementationKhrES; @@ -74,7 +76,8 @@ DebugState::DebugState(Context& context, std::vector& extensions): #endif { if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::EXT::debug_label::string()); + extensions[Extensions::EXT::debug_label::Index] = + Extensions::EXT::debug_label::string(); getLabelImplementation = &AbstractObject::getLabelImplementationExt; labelImplementation = &AbstractObject::labelImplementationExt; @@ -84,14 +87,16 @@ DebugState::DebugState(Context& context, std::vector& extensions): } if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::EXT::debug_marker::string()); + extensions[Extensions::EXT::debug_marker::Index] = + Extensions::EXT::debug_marker::string(); pushGroupImplementation = &DebugGroup::pushImplementationExt; popGroupImplementation = &DebugGroup::popImplementationExt; messageInsertImplementation = &DebugMessage::insertImplementationExt; #ifndef MAGNUM_TARGET_GLES } else if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::GREMEDY::string_marker::string()); + extensions[Extensions::GREMEDY::string_marker::Index] = + Extensions::GREMEDY::string_marker::string(); pushGroupImplementation = &DebugGroup::pushImplementationNoOp; popGroupImplementation = &DebugGroup::popImplementationNoOp; diff --git a/src/Magnum/GL/Implementation/DebugState.h b/src/Magnum/GL/Implementation/DebugState.h index 6205ff109..c537055fe 100644 --- a/src/Magnum/GL/Implementation/DebugState.h +++ b/src/Magnum/GL/Implementation/DebugState.h @@ -25,9 +25,6 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include - #include "Magnum/GL/DebugOutput.h" #include "Magnum/GL/GL.h" @@ -38,7 +35,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct DebugState { - explicit DebugState(Context& context, std::vector& extensions); + explicit DebugState(Context& context, Containers::StaticArrayView extensions); std::string(*getLabelImplementation)(GLenum, GLuint); void(*labelImplementation)(GLenum, GLuint, Containers::ArrayView); diff --git a/src/Magnum/GL/Implementation/FramebufferState.cpp b/src/Magnum/GL/Implementation/FramebufferState.cpp index bae28c63e..38f48883c 100644 --- a/src/Magnum/GL/Implementation/FramebufferState.cpp +++ b/src/Magnum/GL/Implementation/FramebufferState.cpp @@ -39,7 +39,7 @@ using namespace Containers::Literals; constexpr const Range2Di FramebufferState::DisengagedViewport; -FramebufferState::FramebufferState(Context& context, std::vector& extensions): readBinding{0}, drawBinding{0}, renderbufferBinding{0}, maxDrawBuffers{0}, maxColorAttachments{0}, maxRenderbufferSize{0}, +FramebufferState::FramebufferState(Context& context, Containers::StaticArrayView extensions): readBinding{0}, drawBinding{0}, renderbufferBinding{0}, maxDrawBuffers{0}, maxColorAttachments{0}, maxRenderbufferSize{0}, #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) maxSamples{0}, #endif @@ -51,7 +51,9 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Create implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::direct_state_access::string()); + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); + createImplementation = &Framebuffer::createImplementationDSA; createRenderbufferImplementation = &Renderbuffer::createImplementationDSA; @@ -65,7 +67,8 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* DSA/non-DSA implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - /* Extension added above */ + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA; @@ -143,7 +146,8 @@ FramebufferState::FramebufferState(Context& context, std::vector& e } else #endif { - /* Extension name added above */ + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); copySubCubeMapImplementation = &AbstractFramebuffer::copySubCubeMapImplementationDSA; textureCubeMapImplementation = &Framebuffer::textureCubeMapImplementationDSA; @@ -165,7 +169,8 @@ FramebufferState::FramebufferState(Context& context, std::vector& e context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-layered-cubemap-array-framebuffer-attachment"_s)) #endif ) { - /* Extension name added above */ + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); layeredTextureCubeMapArrayImplementation = &Framebuffer::textureImplementationDSA; } else @@ -203,12 +208,16 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Framebuffer texture attachment on ES3 */ #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) - if(context.isVersionSupported(Version::GLES320)) + if(context.isVersionSupported(Version::GLES320)) { textureImplementation = &Framebuffer::textureImplementationDefault; - else if(context.isExtensionSupported()) + } else if(context.isExtensionSupported()) { + extensions[Extensions::EXT::geometry_shader::Index] = + Extensions::EXT::geometry_shader::string(); + textureImplementation = &Framebuffer::textureImplementationEXT; - else + } else { textureImplementation = nullptr; + } #endif #ifdef MAGNUM_TARGET_GLES2 @@ -221,20 +230,24 @@ FramebufferState::FramebufferState(Context& context, std::vector& e checkStatusImplementation = &Framebuffer::checkStatusImplementationDefault; if(context.isExtensionSupported()) { - extensions.push_back(Extensions::ANGLE::framebuffer_blit::string()); + extensions[Extensions::ANGLE::framebuffer_blit::Index] = + Extensions::ANGLE::framebuffer_blit::string(); } else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::APPLE::framebuffer_multisample::string()); + extensions[Extensions::APPLE::framebuffer_multisample::Index] = + Extensions::APPLE::framebuffer_multisample::string(); } else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::NV::framebuffer_blit::string()); + extensions[Extensions::NV::framebuffer_blit::Index] = + Extensions::NV::framebuffer_blit::string(); /* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these enums. However, on my system only NV_framebuffer_multisample is supported, but NV_framebuffer_blit isn't. I will hold my breath and assume these enums are available. */ } else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::NV::framebuffer_multisample::string()); + extensions[Extensions::NV::framebuffer_multisample::Index] = + Extensions::NV::framebuffer_multisample::string(); /* If no such extension is available, reset back to single target */ } else { @@ -249,17 +262,21 @@ FramebufferState::FramebufferState(Context& context, std::vector& e #ifndef MAGNUM_TARGET_WEBGL /* Framebuffer draw mapping on ES2 */ if(context.isExtensionSupported()) { - extensions.push_back(Extensions::EXT::draw_buffers::string()); + extensions[Extensions::EXT::draw_buffers::Index] = + Extensions::EXT::draw_buffers::string(); drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationEXT; } else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::NV::draw_buffers::string()); + extensions[Extensions::NV::draw_buffers::Index] = + Extensions::NV::draw_buffers::string(); drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationNV; } else drawBuffersImplementation = nullptr; #else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::WEBGL::draw_buffers::string()); + extensions[Extensions::WEBGL::draw_buffers::Index] = + Extensions::WEBGL::draw_buffers::string(); + /* The EXT implementation is exposed in Emscripten */ drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationEXT; } else drawBuffersImplementation = nullptr; @@ -296,7 +313,8 @@ FramebufferState::FramebufferState(Context& context, std::vector& e if(context.isExtensionSupported() && !((context.detectedDriver() & Context::DetectedDriver::NVidia) && !context.isDriverWorkaroundDisabled("nv-implementation-color-read-format-dsa-broken"_s)) ) { - /* DSA extension added above */ + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); if((context.detectedDriver() & Context::DetectedDriver::Mesa) && !context.isDriverWorkaroundDisabled("mesa-implementation-color-read-format-dsa-explicit-binding"_s)) implementationColorReadFormatTypeImplementation = &AbstractFramebuffer::implementationColorReadFormatTypeImplementationFramebufferDSAMesa; @@ -319,9 +337,11 @@ FramebufferState::FramebufferState(Context& context, std::vector& e #endif { #ifndef MAGNUM_TARGET_GLES - extensions.emplace_back(Extensions::ARB::robustness::string()); + extensions[Extensions::ARB::robustness::Index] = + Extensions::ARB::robustness::string(); #else - extensions.push_back(Extensions::EXT::robustness::string()); + extensions[Extensions::EXT::robustness::Index] = + Extensions::EXT::robustness::string(); #endif readImplementation = &AbstractFramebuffer::readImplementationRobustness; @@ -335,7 +355,8 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Multisample renderbuffer storage implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - /* Extension added above */ + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationDSA; @@ -344,11 +365,13 @@ FramebufferState::FramebufferState(Context& context, std::vector& e { #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) if(context.isExtensionSupported()) { - extensions.push_back(Extensions::ANGLE::framebuffer_multisample::string()); + extensions[Extensions::ANGLE::framebuffer_multisample::Index] = + Extensions::ANGLE::framebuffer_multisample::string(); renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationANGLE; } else if (context.isExtensionSupported()) { - extensions.push_back(Extensions::NV::framebuffer_multisample::string()); + extensions[Extensions::NV::framebuffer_multisample::Index] = + Extensions::NV::framebuffer_multisample::string(); renderbufferStorageMultisampleImplementation = &Renderbuffer::storageMultisampleImplementationNV; } else renderbufferStorageMultisampleImplementation = nullptr; @@ -360,7 +383,8 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Framebuffer invalidation implementation on desktop GL */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::invalidate_subdata::string()); + extensions[Extensions::ARB::invalidate_subdata::Index] = + Extensions::ARB::invalidate_subdata::string(); if(context.isExtensionSupported()) { /* Extension added above */ @@ -379,7 +403,8 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Framebuffer invalidation implementation on ES2 */ #elif defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) if(context.isExtensionSupported()) { - extensions.push_back(Extensions::EXT::discard_framebuffer::string()); + extensions[Extensions::EXT::discard_framebuffer::Index] = + Extensions::EXT::discard_framebuffer::string(); invalidateImplementation = &AbstractFramebuffer::invalidateImplementationDefault; } else { @@ -395,7 +420,9 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Blit implementation on desktop GL */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - /* Extension added above */ + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); + blitImplementation = &AbstractFramebuffer::blitImplementationDSA; } else blitImplementation = &AbstractFramebuffer::blitImplementationDefault; @@ -403,11 +430,15 @@ FramebufferState::FramebufferState(Context& context, std::vector& e /* Blit implementation on ES2 */ #elif defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) if(context.isExtensionSupported()) { - extensions.push_back(Extensions::ANGLE::framebuffer_blit::string()); + extensions[Extensions::ANGLE::framebuffer_blit::Index] = + Extensions::ANGLE::framebuffer_blit::string(); + blitImplementation = &AbstractFramebuffer::blitImplementationANGLE; } else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::NV::framebuffer_blit::string()); + extensions[Extensions::NV::framebuffer_blit::Index] = + Extensions::NV::framebuffer_blit::string(); + blitImplementation = &AbstractFramebuffer::blitImplementationNV; } else blitImplementation = nullptr; diff --git a/src/Magnum/GL/Implementation/FramebufferState.h b/src/Magnum/GL/Implementation/FramebufferState.h index 8cd0574e2..7b6e9c8d5 100644 --- a/src/Magnum/GL/Implementation/FramebufferState.h +++ b/src/Magnum/GL/Implementation/FramebufferState.h @@ -25,9 +25,6 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include - #include "Magnum/GL/Framebuffer.h" #ifdef _MSC_VER @@ -42,7 +39,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct FramebufferState { constexpr static const Range2Di DisengagedViewport{{}, {-1, -1}}; - explicit FramebufferState(Context& context, std::vector& extensions); + explicit FramebufferState(Context& context, Containers::StaticArrayView extensions); void reset(); diff --git a/src/Magnum/GL/Implementation/MeshState.cpp b/src/Magnum/GL/Implementation/MeshState.cpp index cd44de651..155023482 100644 --- a/src/Magnum/GL/Implementation/MeshState.cpp +++ b/src/Magnum/GL/Implementation/MeshState.cpp @@ -37,7 +37,7 @@ namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -MeshState::MeshState(Context& context, ContextState& contextState, std::vector& extensions): currentVAO(0) +MeshState::MeshState(Context& context, ContextState& contextState, Containers::StaticArrayView extensions): currentVAO(0) #ifndef MAGNUM_TARGET_GLES2 , maxElementIndex{0}, maxElementsIndices{0}, maxElementsVertices{0} #endif @@ -52,9 +52,11 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::EXT::draw_elements_base_vertex::string()); + extensions[Extensions::EXT::draw_elements_base_vertex::Index] = + Extensions::EXT::draw_elements_base_vertex::string(); drawElementsBaseVertexImplementation = glDrawElementsBaseVertexEXT; #ifndef MAGNUM_TARGET_GLES2 @@ -130,7 +134,8 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::OES::draw_elements_base_vertex::string()); + extensions[Extensions::OES::draw_elements_base_vertex::Index] = + Extensions::OES::draw_elements_base_vertex::string(); drawElementsBaseVertexImplementation = glDrawElementsBaseVertexOES; #ifndef MAGNUM_TARGET_GLES2 @@ -140,7 +145,8 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string()); + extensions[Extensions::WEBGL::draw_instanced_base_vertex_base_instance::Index] = + Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string(); /* The WEBGL extension uses the same entrypoints as the ANGLE extension it was based on, however we wrap it to supply trivial instance count @@ -171,7 +177,8 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::ANGLE::base_vertex_base_instance::string()); + extensions[Extensions::ANGLE::base_vertex_base_instance::Index] = + Extensions::ANGLE::base_vertex_base_instance::string(); drawArraysInstancedBaseInstanceImplementation = glDrawArraysInstancedBaseInstanceANGLE; /* This variant isn't in the ext, emulated using @@ -182,7 +189,8 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string()); + extensions[Extensions::WEBGL::draw_instanced_base_vertex_base_instance::Index] = + Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string(); /* The WEBGL extension uses the same entrypoints as the ANGLE extension it was based on. Only available since 1.39.15: @@ -221,19 +229,22 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::EXT::multi_draw_arrays::string()); + extensions[Extensions::EXT::multi_draw_arrays::Index] = + Extensions::EXT::multi_draw_arrays::string(); multiDrawArraysImplementation = glMultiDrawArraysEXT; multiDrawElementsImplementation = glMultiDrawElementsEXT; } else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::ANGLE::multi_draw::string()); + extensions[Extensions::ANGLE::multi_draw::Index] = + Extensions::ANGLE::multi_draw::string(); multiDrawArraysImplementation = glMultiDrawArraysANGLE; multiDrawElementsImplementation = glMultiDrawElementsANGLE; } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); #else { - extensions.push_back(Extensions::WEBGL::multi_draw::string()); + extensions[Extensions::WEBGL::multi_draw::Index] = + Extensions::WEBGL::multi_draw::string(); /* The WEBGL extension uses the same entrypoints as the ANGLE extension it was based on. Only available since 2.0.0: @@ -254,11 +265,13 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::EXT::draw_elements_base_vertex::string()); + extensions[Extensions::EXT::draw_elements_base_vertex::Index] = + Extensions::EXT::draw_elements_base_vertex::string(); multiDrawElementsBaseVertexImplementation = glMultiDrawElementsBaseVertexEXT; } else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::OES::draw_elements_base_vertex::string()); + extensions[Extensions::OES::draw_elements_base_vertex::Index] = + Extensions::OES::draw_elements_base_vertex::string(); /* Yes, it's really EXT, the same as with EXT_draw_elements_base_vertex. I have no idea why the two @@ -267,7 +280,8 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string()); + extensions[Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::Index] = + Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string(); /* The WEBGL extension uses the same entrypoints as the ANGLE extension it was based on, however we wrap it and supply trivial @@ -295,7 +309,8 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) { - extensions.push_back(Extensions::ANGLE::instanced_arrays::string()); + extensions[Extensions::ANGLE::instanced_arrays::Index] = + Extensions::ANGLE::instanced_arrays::string(); drawArraysInstancedImplementation = glDrawArraysInstancedANGLE; drawElementsInstancedImplementation = glDrawElementsInstancedANGLE; @@ -303,18 +318,22 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector() || context.isExtensionSupported()) { - extensions.push_back(context.isExtensionSupported() ? - Extensions::EXT::instanced_arrays::string() : - Extensions::EXT::draw_instanced::string()); + if(context.isExtensionSupported()) + extensions[Extensions::EXT::instanced_arrays::Index] = + Extensions::EXT::instanced_arrays::string(); + else extensions[Extensions::EXT::draw_instanced::Index] = + Extensions::EXT::draw_instanced::string(); drawArraysInstancedImplementation = glDrawArraysInstancedEXT; drawElementsInstancedImplementation = glDrawElementsInstancedEXT; } else if(context.isExtensionSupported() || context.isExtensionSupported()) { - extensions.push_back(context.isExtensionSupported() ? - Extensions::NV::instanced_arrays::string() : - Extensions::NV::draw_instanced::string()); + if(context.isExtensionSupported()) + extensions[Extensions::NV::instanced_arrays::Index] = + Extensions::NV::instanced_arrays::string(); + else extensions[Extensions::NV::draw_instanced::Index] = + Extensions::NV::draw_instanced::string(); drawArraysInstancedImplementation = glDrawArraysInstancedNV; drawElementsInstancedImplementation = glDrawElementsInstancedNV; @@ -332,27 +351,37 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector()) + } else if(context.isExtensionSupported()) { + extensions[Extensions::ARB::vertex_array_object::Index] = + Extensions::ARB::vertex_array_object::string(); + vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationVAO; - else + } else { vertexAttribDivisorImplementation = nullptr; + } #elif defined(MAGNUM_TARGET_GLES2) /* Instanced arrays implementation on ES2 */ if(context.isExtensionSupported()) { - /* Extension added above */ + extensions[Extensions::ANGLE::instanced_arrays::Index] = + Extensions::ANGLE::instanced_arrays::string(); vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationANGLE; } #ifndef MAGNUM_TARGET_WEBGL else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::EXT::instanced_arrays::string()); + extensions[Extensions::EXT::instanced_arrays::Index] = + Extensions::EXT::instanced_arrays::string(); vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationEXT; } else if(context.isExtensionSupported()) { - extensions.push_back(Extensions::NV::instanced_arrays::string()); + extensions[Extensions::NV::instanced_arrays::Index] = + Extensions::NV::instanced_arrays::string(); vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationNV; } diff --git a/src/Magnum/GL/Implementation/MeshState.h b/src/Magnum/GL/Implementation/MeshState.h index 30a6034f0..13a46478b 100644 --- a/src/Magnum/GL/Implementation/MeshState.h +++ b/src/Magnum/GL/Implementation/MeshState.h @@ -25,9 +25,6 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include - #include "Magnum/GL/Mesh.h" namespace Magnum { namespace GL { namespace Implementation { @@ -35,7 +32,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct ContextState; struct MeshState { - explicit MeshState(Context& context, ContextState& contextState, std::vector& extensions); + explicit MeshState(Context& context, ContextState& contextState, Containers::StaticArrayView extensions); ~MeshState(); void reset(); diff --git a/src/Magnum/GL/Implementation/QueryState.cpp b/src/Magnum/GL/Implementation/QueryState.cpp index 41fb3168d..debc507b9 100644 --- a/src/Magnum/GL/Implementation/QueryState.cpp +++ b/src/Magnum/GL/Implementation/QueryState.cpp @@ -35,7 +35,7 @@ namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -QueryState::QueryState(Context& context, std::vector& extensions) { +QueryState::QueryState(Context& context, Containers::StaticArrayView extensions) { /* Create implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { @@ -43,15 +43,21 @@ QueryState::QueryState(Context& context, std::vector& extensions) { if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-indexed-queries"_s)) { createImplementation = &AbstractQuery::createImplementationDefault; } else if((context.detectedDriver() & Context::DetectedDriver::Amd) && !context.isDriverWorkaroundDisabled("amd-windows-dsa-createquery-except-xfb-overflow"_s)) { - extensions.emplace_back(Extensions::ARB::direct_state_access::string()); + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); + createImplementation = &AbstractQuery::createImplementationDSAExceptXfbOverflow; } else #endif if((context.detectedDriver() & Context::DetectedDriver::Mesa) && !context.isDriverWorkaroundDisabled("mesa-dsa-createquery-except-pipeline-stats"_s)) { - extensions.emplace_back(Extensions::ARB::direct_state_access::string()); + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); + createImplementation = &AbstractQuery::createImplementationDSAExceptPipelineStats; } else { - extensions.emplace_back(Extensions::ARB::direct_state_access::string()); + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); + createImplementation = &AbstractQuery::createImplementationDSA; } } else diff --git a/src/Magnum/GL/Implementation/QueryState.h b/src/Magnum/GL/Implementation/QueryState.h index bf30c2870..caf9f3db6 100644 --- a/src/Magnum/GL/Implementation/QueryState.h +++ b/src/Magnum/GL/Implementation/QueryState.h @@ -25,9 +25,7 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include - +#include "Magnum/Magnum.h" #include "Magnum/GL/GL.h" #ifdef _MSC_VER @@ -40,7 +38,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct QueryState { - explicit QueryState(Context& context, std::vector& extensions); + explicit QueryState(Context& context, Containers::StaticArrayView extensions); void reset(); diff --git a/src/Magnum/GL/Implementation/RendererState.cpp b/src/Magnum/GL/Implementation/RendererState.cpp index 6ebd3f909..706fd3503 100644 --- a/src/Magnum/GL/Implementation/RendererState.cpp +++ b/src/Magnum/GL/Implementation/RendererState.cpp @@ -35,7 +35,7 @@ namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -RendererState::RendererState(Context& context, ContextState& contextState, std::vector& extensions) +RendererState::RendererState(Context& context, ContextState& contextState, Containers::StaticArrayView extensions) #ifndef MAGNUM_TARGET_WEBGL : resetNotificationStrategy() #endif @@ -46,7 +46,8 @@ RendererState::RendererState(Context& context, ContextState& contextState, std:: #endif { #ifndef MAGNUM_TARGET_GLES - extensions.emplace_back(Extensions::ARB::ES2_compatibility::string()); + extensions[Extensions::ARB::ES2_compatibility::Index] = + Extensions::ARB::ES2_compatibility::string(); #endif clearDepthfImplementation = &Renderer::clearDepthfImplementationES; @@ -64,9 +65,11 @@ RendererState::RendererState(Context& context, ContextState& contextState, std:: #endif { #ifndef MAGNUM_TARGET_GLES - extensions.emplace_back(Extensions::ARB::robustness::string()); + extensions[Extensions::ARB::robustness::Index] = + Extensions::ARB::robustness::string(); #else - extensions.push_back(Extensions::EXT::robustness::string()); + extensions[Extensions::EXT::robustness::Index] = + Extensions::EXT::robustness::string(); #endif graphicsResetStatusImplementation = &Renderer::graphicsResetStatusImplementationRobustness; @@ -103,12 +106,16 @@ RendererState::RendererState(Context& context, ContextState& contextState, std:: #ifndef MAGNUM_TARGET_GLES minSampleShadingImplementation = &Renderer::minSampleShadingImplementationDefault; #elif !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(context.isVersionSupported(Version::GLES320)) + if(context.isVersionSupported(Version::GLES320)) { minSampleShadingImplementation = &Renderer::minSampleShadingImplementationDefault; - else if(context.isExtensionSupported()) + } else if(context.isExtensionSupported()) { + extensions[Extensions::OES::sample_shading::Index] = + Extensions::OES::sample_shading::string(); + minSampleShadingImplementation = &Renderer::minSampleShadingImplementationOES; - else + } else { minSampleShadingImplementation = nullptr; + } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) diff --git a/src/Magnum/GL/Implementation/RendererState.h b/src/Magnum/GL/Implementation/RendererState.h index 0ff9abde7..f8f91034d 100644 --- a/src/Magnum/GL/Implementation/RendererState.h +++ b/src/Magnum/GL/Implementation/RendererState.h @@ -25,9 +25,6 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include - #include "Magnum/GL/Renderer.h" #include "Magnum/Math/Range.h" @@ -36,7 +33,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct ContextState; struct RendererState { - explicit RendererState(Context& context, ContextState& contextState, std::vector& extensions); + explicit RendererState(Context& context, ContextState& contextState, Containers::StaticArrayView extensions); Range1D(*lineWidthRangeImplementation)(); void(*clearDepthfImplementation)(GLfloat); diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.cpp b/src/Magnum/GL/Implementation/ShaderProgramState.cpp index e22fc5190..141197fce 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/GL/Implementation/ShaderProgramState.cpp @@ -37,7 +37,7 @@ namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -ShaderProgramState::ShaderProgramState(Context& context, std::vector& extensions): current(0), maxVertexAttributes(0) +ShaderProgramState::ShaderProgramState(Context& context, Containers::StaticArrayView extensions): current(0), maxVertexAttributes(0) #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_WEBGL , maxGeometryOutputVertices{0}, maxAtomicCounterBufferSize(0), maxComputeSharedMemorySize(0), maxComputeWorkGroupInvocations(0), maxImageUnits(0), maxCombinedShaderOutputResources(0), maxUniformLocations(0) @@ -86,7 +86,8 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector()) { - extensions.push_back(Extensions::EXT::separate_shader_objects::string()); + extensions[Extensions::EXT::separate_shader_objects::Index] = + Extensions::EXT::separate_shader_objects::string(); uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.h b/src/Magnum/GL/Implementation/ShaderProgramState.h index 42e925ef6..92f68c5c7 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.h +++ b/src/Magnum/GL/Implementation/ShaderProgramState.h @@ -25,9 +25,9 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include +#include +#include "Magnum/Magnum.h" #include "Magnum/GL/GL.h" #include "Magnum/GL/OpenGL.h" #include "Magnum/Math/Vector3.h" @@ -39,7 +39,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct ShaderProgramState { - explicit ShaderProgramState(Context& context, std::vector& extensions); + explicit ShaderProgramState(Context& context, Containers::StaticArrayView extensions); void reset(); diff --git a/src/Magnum/GL/Implementation/ShaderState.cpp b/src/Magnum/GL/Implementation/ShaderState.cpp index 391d03b05..da221fafa 100644 --- a/src/Magnum/GL/Implementation/ShaderState.cpp +++ b/src/Magnum/GL/Implementation/ShaderState.cpp @@ -36,7 +36,7 @@ namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -ShaderState::ShaderState(Context& context, std::vector&): +ShaderState::ShaderState(Context& context, Containers::StaticArrayView): maxVertexOutputComponents{}, maxFragmentInputComponents{}, #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) maxTessellationControlInputComponents{}, maxTessellationControlOutputComponents{}, maxTessellationControlTotalOutputComponents{}, maxTessellationEvaluationInputComponents{}, maxTessellationEvaluationOutputComponents{}, maxGeometryInputComponents{}, maxGeometryOutputComponents{}, maxGeometryTotalOutputComponents{}, maxAtomicCounterBuffers{}, maxCombinedAtomicCounterBuffers{}, maxAtomicCounters{}, maxCombinedAtomicCounters{}, maxImageUniforms{}, maxCombinedImageUniforms{}, maxShaderStorageBlocks{}, maxCombinedShaderStorageBlocks{}, diff --git a/src/Magnum/GL/Implementation/ShaderState.h b/src/Magnum/GL/Implementation/ShaderState.h index 7dd6fc52a..1cd83ef77 100644 --- a/src/Magnum/GL/Implementation/ShaderState.h +++ b/src/Magnum/GL/Implementation/ShaderState.h @@ -25,9 +25,9 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include +#include +#include "Magnum/Magnum.h" #include "Magnum/GL/GL.h" #include "Magnum/GL/OpenGL.h" @@ -41,7 +41,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct ShaderState { - explicit ShaderState(Context& context, std::vector& extensions); + explicit ShaderState(Context& context, Containers::StaticArrayView extensions); enum: std::size_t { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) diff --git a/src/Magnum/GL/Implementation/State.cpp b/src/Magnum/GL/Implementation/State.cpp index 909baff9f..558f87776 100644 --- a/src/Magnum/GL/Implementation/State.cpp +++ b/src/Magnum/GL/Implementation/State.cpp @@ -25,9 +25,6 @@ #include "State.h" -#include -#include - #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" #include "Magnum/GL/Implementation/BufferState.h" @@ -49,14 +46,12 @@ namespace Magnum { namespace GL { namespace Implementation { State::State(Context& context, std::ostream* const out) { - /* List of extensions used in current context. Guesstimate count to avoid - unnecessary reallocations. */ - std::vector extensions; - #ifndef MAGNUM_TARGET_GLES - extensions.reserve(32); - #else - extensions.reserve(8); - #endif + /* Extensions that might get used by current context. The State classes + will set strings based on Extension::index() and then we'll go through + the list and print ones that aren't null. It's 1.5 kB of temporary data + but I think in terms of code size and overhead it's better than + populating a heap array and then std::sort() it to remove duplicates. */ + const char* extensions[Implementation::ExtensionCount]{}; buffer.reset(new BufferState{context, extensions}); this->context.reset(new ContextState{context, extensions}); @@ -74,12 +69,9 @@ State::State(Context& context, std::ostream* const out) { transformFeedback.reset(new TransformFeedbackState{context, extensions}); #endif - /* Sort the features and remove duplicates */ - std::sort(extensions.begin(), extensions.end()); - extensions.erase(std::unique(extensions.begin(), extensions.end()), extensions.end()); - Debug{out} << "Using optional features:"; - for(const auto& ext: extensions) Debug(out) << " " << ext; + for(const char* extension: extensions) + if(extension) Debug(out) << " " << extension; } State::~State() = default; diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index f96b2987a..aca81d760 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -43,7 +43,7 @@ namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -TextureState::TextureState(Context& context, std::vector& extensions): maxSize{}, +TextureState::TextureState(Context& context, Containers::StaticArrayView extensions): maxSize{}, #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) max3DSize{}, #endif @@ -69,7 +69,8 @@ TextureState::TextureState(Context& context, std::vector& extension /* Create implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::direct_state_access::string()); + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); createImplementation = &AbstractTexture::createImplementationDSA; } else @@ -114,7 +115,8 @@ TextureState::TextureState(Context& context, std::vector& extension /* Multi bind implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::multi_bind::string()); + extensions[Extensions::ARB::multi_bind::Index] = + Extensions::ARB::multi_bind::string(); bindMultiImplementation = &AbstractTexture::bindImplementationMulti; @@ -127,7 +129,8 @@ TextureState::TextureState(Context& context, std::vector& extension /* DSA/non-DSA implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::direct_state_access::string()); + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); parameteriImplementation = &AbstractTexture::parameterImplementationDSA; parameterfImplementation = &AbstractTexture::parameterImplementationDSA; @@ -244,7 +247,8 @@ TextureState::TextureState(Context& context, std::vector& extension /* Data invalidation implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::invalidate_subdata::string()); + extensions[Extensions::ARB::invalidate_subdata::Index] = + Extensions::ARB::invalidate_subdata::string(); invalidateImageImplementation = &AbstractTexture::invalidateImageImplementationARB; invalidateSubImageImplementation = &AbstractTexture::invalidateSubImageImplementationARB; @@ -281,7 +285,9 @@ TextureState::TextureState(Context& context, std::vector& extension getCompressedImageImplementation = &AbstractTexture::getCompressedImageImplementationDSA; } else if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::robustness::string()); + extensions[Extensions::ARB::robustness::Index] = + Extensions::ARB::robustness::string(); + getImageImplementation = &AbstractTexture::getImageImplementationRobustness; getCompressedImageImplementation = &AbstractTexture::getCompressedImageImplementationRobustness; @@ -292,7 +298,9 @@ TextureState::TextureState(Context& context, std::vector& extension /* Image retrieval implementation for cube map */ if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::get_texture_sub_image::string()); + extensions[Extensions::ARB::get_texture_sub_image::Index] = + Extensions::ARB::get_texture_sub_image::string(); + getCubeImageImplementation = &CubeMapTexture::getImageImplementationDSA; getCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSA; @@ -342,9 +350,11 @@ TextureState::TextureState(Context& context, std::vector& extension #endif { #ifndef MAGNUM_TARGET_GLES - extensions.emplace_back(Extensions::ARB::texture_storage::string()); + extensions[Extensions::ARB::texture_storage::Index] = + Extensions::ARB::texture_storage::string(); #elif defined(MAGNUM_TARGET_GLES2) - extensions.push_back(Extensions::EXT::texture_storage::string()); + extensions[Extensions::EXT::texture_storage::Index] = + Extensions::EXT::texture_storage::string(); #endif #ifndef MAGNUM_TARGET_GLES @@ -387,7 +397,8 @@ TextureState::TextureState(Context& context, std::vector& extension /* Storage implementation for multisample textures. The fallback doesn't have DSA alternative, so it must be handled specially. */ if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::texture_storage_multisample::string()); + extensions[Extensions::ARB::texture_storage_multisample::Index] = + Extensions::ARB::texture_storage_multisample::string(); if(context.isExtensionSupported()) { storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDSA; @@ -403,24 +414,30 @@ TextureState::TextureState(Context& context, std::vector& extension #elif !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) storage2DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault; - if(context.isVersionSupported(Version::GLES320)) + if(context.isVersionSupported(Version::GLES320)) { storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationDefault; - else if(context.isExtensionSupported()) + } else if(context.isExtensionSupported()) { + extensions[Extensions::OES::texture_storage_multisample_2d_array::Index] = + Extensions::OES::texture_storage_multisample_2d_array::string(); + storage3DMultisampleImplementation = &AbstractTexture::storageMultisampleImplementationOES; - else + } else { storage3DMultisampleImplementation = nullptr; + } #endif /* Anisotropic filter implementation */ #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::ARB::texture_filter_anisotropic::string()); + extensions[Extensions::ARB::texture_filter_anisotropic::Index] = + Extensions::ARB::texture_filter_anisotropic::string(); setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationArb; } else #endif if(context.isExtensionSupported()) { - extensions.emplace_back(Extensions::EXT::texture_filter_anisotropic::string()); + extensions[Extensions::EXT::texture_filter_anisotropic::Index] = + Extensions::EXT::texture_filter_anisotropic::string(); setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt; } else setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationNoOp; diff --git a/src/Magnum/GL/Implementation/TextureState.h b/src/Magnum/GL/Implementation/TextureState.h index 2a33eff88..f36f76811 100644 --- a/src/Magnum/GL/Implementation/TextureState.h +++ b/src/Magnum/GL/Implementation/TextureState.h @@ -25,8 +25,6 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include #include #include @@ -53,7 +51,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct TextureState { - explicit TextureState(Context& context, std::vector& extensions); + explicit TextureState(Context& context, Containers::StaticArrayView extensions); ~TextureState(); void reset(); diff --git a/src/Magnum/GL/Implementation/TransformFeedbackState.cpp b/src/Magnum/GL/Implementation/TransformFeedbackState.cpp index 7ce2fbb4a..5a0b6855d 100644 --- a/src/Magnum/GL/Implementation/TransformFeedbackState.cpp +++ b/src/Magnum/GL/Implementation/TransformFeedbackState.cpp @@ -7,7 +7,7 @@ namespace Magnum { namespace GL { namespace Implementation { -TransformFeedbackState::TransformFeedbackState(Context& context, std::vector& extensions): maxInterleavedComponents{0}, maxSeparateAttributes{0}, maxSeparateComponents{0}, +TransformFeedbackState::TransformFeedbackState(Context& context, Containers::StaticArrayView extensions): maxInterleavedComponents{0}, maxSeparateAttributes{0}, maxSeparateComponents{0}, #ifndef MAGNUM_TARGET_GLES maxBuffers{0}, maxVertexStreams{0}, #endif @@ -15,7 +15,8 @@ TransformFeedbackState::TransformFeedbackState(Context& context, std::vector()) { - extensions.emplace_back(Extensions::ARB::direct_state_access::string()); + extensions[Extensions::ARB::direct_state_access::Index] = + Extensions::ARB::direct_state_access::string(); createImplementation = &TransformFeedback::createImplementationDSA; attachRangeImplementation = &TransformFeedback::attachImplementationDSA; diff --git a/src/Magnum/GL/Implementation/TransformFeedbackState.h b/src/Magnum/GL/Implementation/TransformFeedbackState.h index add8477d4..d146fa638 100644 --- a/src/Magnum/GL/Implementation/TransformFeedbackState.h +++ b/src/Magnum/GL/Implementation/TransformFeedbackState.h @@ -25,9 +25,10 @@ DEALINGS IN THE SOFTWARE. */ -#include -#include +#include +#include +#include "Magnum/Magnum.h" #include "Magnum/GL/GL.h" #include "Magnum/GL/OpenGL.h" @@ -45,7 +46,7 @@ namespace Magnum { namespace GL { namespace Implementation { struct TransformFeedbackState { - explicit TransformFeedbackState(Context& context, std::vector& extensions); + explicit TransformFeedbackState(Context& context, Containers::StaticArrayView extensions); void reset(); From f6bb30d6d0b05c3b16ea300d9ce775e39243a1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Feb 2021 20:16:59 +0100 Subject: [PATCH 012/161] GL: apparently some of these aren't needed to be called everywhere. StringViews are great -- given that they are trivially destructible, the compiler can now tell me that I have unused variables. If it wouldn't be trivially destructible (like std::string), the destructor is treated as if it has side-effects so the compiler won't complain. --- src/Magnum/GL/Implementation/driverSpecific.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Magnum/GL/Implementation/driverSpecific.cpp b/src/Magnum/GL/Implementation/driverSpecific.cpp index 45ef76398..9b681b544 100644 --- a/src/Magnum/GL/Implementation/driverSpecific.cpp +++ b/src/Magnum/GL/Implementation/driverSpecific.cpp @@ -415,9 +415,15 @@ auto Context::detectedDriver() -> DetectedDrivers { _detectedDrivers = DetectedDrivers{}; + #ifndef MAGNUM_TARGET_WEBGL const Containers::StringView renderer = rendererString(); - const Containers::StringView vendor = vendorString(); + #endif + #if !defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_WEBGL) const Containers::StringView version = versionString(); + #endif + #if (!defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_WEBGL)) || defined(MAGNUM_TARGET_GLES) + const Containers::StringView vendor = vendorString(); + #endif /* Apple has its own drivers */ #if !defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_WEBGL) From 8984157db505e741dafe96a7865143eb1bbf554a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Feb 2021 20:19:09 +0100 Subject: [PATCH 013/161] Vk: sprinkle a bunch of consts here and there. --- src/Magnum/Vk/Device.cpp | 6 +++--- src/Magnum/Vk/Implementation/DriverWorkaround.cpp | 8 ++++---- src/Magnum/Vk/Instance.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp index 0f719eea2..285a01635 100644 --- a/src/Magnum/Vk/Device.cpp +++ b/src/Magnum/Vk/Device.cpp @@ -141,9 +141,9 @@ DeviceCreateInfo::DeviceCreateInfo(DeviceProperties& deviceProperties, const Ext we don't need to bother with String allocations. */ Containers::StringView disabledWorkarounds = args.value("disable-workarounds"); if(!disabledWorkarounds.isEmpty()) { - Containers::Array split = disabledWorkarounds.splitWithoutEmptyParts(); + const Containers::Array split = disabledWorkarounds.splitWithoutEmptyParts(); arrayReserve(_state->encounteredWorkarounds, split.size()); - for(Containers::StringView workaround: split) + for(const Containers::StringView workaround: split) Implementation::disableWorkaround(_state->encounteredWorkarounds, workaround); } @@ -837,7 +837,7 @@ template void Device::initializeExtensions(const Containers::ArrayView< for(const Version version: KnownVersionsForExtensions) { const Containers::ArrayView knownExtensions = Extension::extensions(version); - auto found = std::lower_bound(knownExtensions.begin(), knownExtensions.end(), extension, [](const Extension& a, const T& b) { + const auto found = std::lower_bound(knownExtensions.begin(), knownExtensions.end(), extension, [](const Extension& a, const T& b) { return a.string() < static_cast(b); }); if(found->string() != extension) continue; diff --git a/src/Magnum/Vk/Implementation/DriverWorkaround.cpp b/src/Magnum/Vk/Implementation/DriverWorkaround.cpp index e030c5a24..3df15b989 100644 --- a/src/Magnum/Vk/Implementation/DriverWorkaround.cpp +++ b/src/Magnum/Vk/Implementation/DriverWorkaround.cpp @@ -78,8 +78,8 @@ constexpr Containers::StringView KnownWorkarounds[]{ Moreover, based on the experience with GL, I don't expect there being too many workarounds used heavily (10 at most, maybe?) so I won't bother with some binary search, which needs extra testing effort. */ -Containers::StringView findWorkaround(Containers::StringView workaround) { - for(Containers::StringView i: KnownWorkarounds) +Containers::StringView findWorkaround(const Containers::StringView workaround) { + for(const Containers::StringView i: KnownWorkarounds) if(workaround == i) return i; return {}; } @@ -90,7 +90,7 @@ void disableWorkaround(Containers::Array /* Find the workaround. Note that we'll add the found view to the array and not the passed view, as the found view is guaranteed to stay in scope */ - Containers::StringView found = findWorkaround(workaround); + const Containers::StringView found = findWorkaround(workaround); /* Ignore unknown workarounds */ /** @todo this will probably cause false positives when both GL and Vulkan @@ -105,7 +105,7 @@ void disableWorkaround(Containers::Array Containers::Array> disableAllWorkarounds() { Containers::Array> encounteredWorkarounds; - for(Containers::StringView i: KnownWorkarounds) + for(const Containers::StringView i: KnownWorkarounds) arrayAppend(encounteredWorkarounds, Containers::InPlaceInit, i, true); return encounteredWorkarounds; } diff --git a/src/Magnum/Vk/Instance.cpp b/src/Magnum/Vk/Instance.cpp index dcc30c0ea..3134c5858 100644 --- a/src/Magnum/Vk/Instance.cpp +++ b/src/Magnum/Vk/Instance.cpp @@ -355,7 +355,7 @@ template void Instance::initializeExtensions(const Containers::ArrayVie InstanceExtension::extensions(Version::Vk11), /*InstanceExtension::extensions(Version::Vk12) is empty */ }) { - auto found = std::lower_bound(knownExtensions.begin(), knownExtensions.end(), extension, [](const InstanceExtension& a, const T& b) { + const auto found = std::lower_bound(knownExtensions.begin(), knownExtensions.end(), extension, [](const InstanceExtension& a, const T& b) { return a.string() < static_cast(b); }); if(found->string() != extension) continue; From 3622da8fb767d02b8354c0c1ccdaffdd5c1d1706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 22 Feb 2021 20:19:24 +0100 Subject: [PATCH 014/161] Vk: minor OCD thing. --- src/Magnum/Vk/Extensions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Vk/Extensions.h b/src/Magnum/Vk/Extensions.h index 41c7b6cef..d86f4db79 100644 --- a/src/Magnum/Vk/Extensions.h +++ b/src/Magnum/Vk/Extensions.h @@ -80,7 +80,7 @@ namespace Extensions { constexpr static Version coreVersion() { return Version::_coreVersion; } \ constexpr static Containers::StringView string() { \ using namespace Containers::Literals; \ - return "VK_" #vendor "_" #extension ""_s; \ + return "VK_" #vendor "_" #extension ""_s; \ } \ }; namespace EXT { From 294c910d441d96a5c0a005e9d0f7c603c44f197c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 23 Feb 2021 00:04:28 +0100 Subject: [PATCH 015/161] MeshTools: don't #include unless absolutely necessary. --- src/Magnum/MeshTools/FlipNormals.cpp | 2 ++ src/Magnum/MeshTools/Test/CompressIndicesTest.cpp | 5 ++++- src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Magnum/MeshTools/FlipNormals.cpp b/src/Magnum/MeshTools/FlipNormals.cpp index c72d66e46..c13094726 100644 --- a/src/Magnum/MeshTools/FlipNormals.cpp +++ b/src/Magnum/MeshTools/FlipNormals.cpp @@ -25,7 +25,9 @@ #include "FlipNormals.h" +#ifdef MAGNUM_BUILD_DEPRECATED #include +#endif #include #include "Magnum/Math/Vector3.h" diff --git a/src/Magnum/MeshTools/Test/CompressIndicesTest.cpp b/src/Magnum/MeshTools/Test/CompressIndicesTest.cpp index 63ddff551..56332395f 100644 --- a/src/Magnum/MeshTools/Test/CompressIndicesTest.cpp +++ b/src/Magnum/MeshTools/Test/CompressIndicesTest.cpp @@ -24,7 +24,6 @@ */ #include -#include #include #include #include @@ -36,6 +35,10 @@ #include "Magnum/MeshTools/CompressIndices.h" #include "Magnum/Trade/MeshData.h" +#ifdef MAGNUM_BUILD_DEPRECATED +#include +#endif + namespace Magnum { namespace MeshTools { namespace Test { namespace { struct CompressIndicesTest: TestSuite::Tester { diff --git a/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp b/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp index db209edee..969c4bdc0 100644 --- a/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp +++ b/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp @@ -24,7 +24,6 @@ */ #include -#include #include #include #include @@ -39,6 +38,10 @@ #include "Magnum/Primitives/Cylinder.h" #include "Magnum/Trade/MeshData.h" +#ifdef MAGNUM_BUILD_DEPRECATED +#include +#endif + namespace Magnum { namespace MeshTools { namespace Test { namespace { struct GenerateNormalsTest: TestSuite::Tester { From df3184f0bcecb9cc2f66b535d9a7998714c2bb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 23 Feb 2021 18:55:23 +0100 Subject: [PATCH 016/161] Platform: remove full value specification from Flags EnumSets. I don't see any use case for just specifying "all the flags", mainly because the flags are mutually conflicting and whatnot. Also, these go outdated *fast*. --- src/Magnum/Platform/Sdl2Application.h | 9 --------- src/Magnum/Platform/WindowlessEglApplication.h | 8 -------- src/Magnum/Platform/WindowlessGlxApplication.h | 8 -------- src/Magnum/Platform/WindowlessWglApplication.h | 8 -------- src/Magnum/Platform/WindowlessWindowsEglApplication.h | 4 ---- 5 files changed, 37 deletions(-) diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 20c619c57..ec37791f6 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -1269,17 +1269,8 @@ class Sdl2Application::GLConfiguration { * @see @ref setFlags(), @ref GL::Context::Flags * @requires_gles Context flags are not available in WebGL. */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else typedef Containers::EnumSet Flags; #endif - #endif explicit GLConfiguration(); ~GLConfiguration(); diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index 91b4a4604..e9b9f06bb 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -213,16 +213,8 @@ class WindowlessEglContext::Configuration { * @see @ref setFlags(), @ref Context::Flags * @requires_gles Context flags are not available in WebGL. */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else typedef Containers::EnumSet Flags; #endif - #endif /*implicit*/ Configuration(); diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 68dc2d591..2647d7fac 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -216,15 +216,7 @@ class WindowlessGlxContext::Configuration { * * @see @ref setFlags(), @ref Context::Flags */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else typedef Containers::EnumSet Flags; - #endif /*implicit*/ Configuration(); diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 5deb05a9c..3ff1021b0 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -203,15 +203,7 @@ class WindowlessWglContext::Configuration { * * @see @ref setFlags(), @ref Context::Flags */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else typedef Containers::EnumSet Flags; - #endif /*implicit*/ Configuration(); diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 589be9571..06c209bb0 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -179,11 +179,7 @@ class WindowlessWindowsEglContext::Configuration { * * @see @ref setFlags(), @ref Context::Flags */ - #ifndef DOXYGEN_GENERATING_OUTPUT - typedef Containers::EnumSet Flags; - #else typedef Containers::EnumSet Flags; - #endif constexpr /*implicit*/ Configuration() {} From 49630d43d4f5f8f1d0e74f9fc2b1b78a2a9764a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 11:15:36 +0100 Subject: [PATCH 017/161] GL: add a type trait for checking if a type is an extension. Similar to what Vulkan has. Will be used mainly for guarding implicit conversion to the Extension class. --- src/Magnum/GL/Context.h | 29 +++++++++++++------ src/Magnum/GL/Test/ContextTest.cpp | 45 +++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 54c2e7f5e..45bb43794 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -57,6 +57,14 @@ namespace GL { namespace Implementation { struct ContextState; struct State; + + template class IsExtension; + template<> class IsExtension<> { public: enum: bool { value = true }; }; + CORRADE_HAS_TYPE(IsExtension, decltype(T::Index)); + template class IsExtension { + /** @todo C++17: use &&... instead of all this */ + public: enum: bool { value = IsExtension::value && IsExtension::value }; + }; } /** @@ -650,8 +658,8 @@ class MAGNUM_GL_EXPORT Context { * @ref MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(), * @ref isExtensionDisabled() */ - template bool isExtensionSupported() const { - return isExtensionSupported(version()); + template bool isExtensionSupported() const { + return isExtensionSupported(version()); } /** @@ -664,8 +672,9 @@ class MAGNUM_GL_EXPORT Context { * * @snippet MagnumGL.cpp Context-isExtensionSupported-version */ - template bool isExtensionSupported(Version version) const { - return _extensionRequiredVersion[T::Index] <= version && _extensionStatus[T::Index]; + template bool isExtensionSupported(Version version) const { + static_assert(Implementation::IsExtension::value, "expected an OpenGL extension"); + return _extensionRequiredVersion[E::Index] <= version && _extensionStatus[E::Index]; } /** @@ -688,8 +697,8 @@ class MAGNUM_GL_EXPORT Context { * extensions return `false` in @ref isExtensionSupported() even if * they are advertised as being supported by the driver. */ - template bool isExtensionDisabled() const { - return isExtensionDisabled(version()); + template bool isExtensionDisabled() const { + return isExtensionDisabled(version()); } /** @@ -698,9 +707,11 @@ class MAGNUM_GL_EXPORT Context { * Similar to above, but can also check for extensions which are * disabled only for particular versions. */ - template bool isExtensionDisabled(Version version) const { - /* The extension is advertised, but the minimal version has been increased */ - return T::requiredVersion() <= version && _extensionRequiredVersion[T::Index] > version; + template bool isExtensionDisabled(Version version) const { + static_assert(Implementation::IsExtension::value, "expected an OpenGL extension"); + /* The extension is advertised, but the minimal version has been + increased */ + return E::requiredVersion() <= version && _extensionRequiredVersion[E::Index] > version; } /** diff --git a/src/Magnum/GL/Test/ContextTest.cpp b/src/Magnum/GL/Test/ContextTest.cpp index 12e626180..c393e1048 100644 --- a/src/Magnum/GL/Test/ContextTest.cpp +++ b/src/Magnum/GL/Test/ContextTest.cpp @@ -37,6 +37,8 @@ namespace Magnum { namespace GL { namespace Test { namespace { struct ContextTest: TestSuite::Tester { explicit ContextTest(); + void isExtension(); + void constructNoCreate(); void constructCopyMove(); @@ -52,7 +54,9 @@ struct ContextTest: TestSuite::Tester { }; ContextTest::ContextTest() { - addTests({&ContextTest::constructNoCreate, + addTests({&ContextTest::isExtension, + + &ContextTest::constructNoCreate, &ContextTest::constructCopyMove, &ContextTest::makeCurrentNoOp, @@ -66,6 +70,45 @@ ContextTest::ContextTest() { &ContextTest::debugDetectedDrivers}); } +void ContextTest::isExtension() { + CORRADE_VERIFY(Implementation::IsExtension::value); + CORRADE_VERIFY(!Implementation::IsExtension::value); + CORRADE_VERIFY(!Implementation::IsExtension::value); + + { + /* Not really a problem right now, but once people hit this we might + want to guard against this (especially because the Index might be + out of bounds) */ + struct ALExtension { + enum: std::size_t { Index }; + }; + CORRADE_EXPECT_FAIL("AL/Vk extensions are not rejected right now."); + CORRADE_VERIFY(!Implementation::IsExtension::value); + } + + /* Variadic check (used in variadic addEnabledExtensions()), check that it + properly fails for each occurence of a non-extension */ + CORRADE_VERIFY((Implementation::IsExtension< + Extensions::KHR::debug, + Extensions::EXT::texture_filter_anisotropic, + Extensions::KHR::texture_compression_astc_hdr>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extension, + Extensions::KHR::debug, + Extensions::EXT::texture_filter_anisotropic>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::KHR::debug, + Extension, + Extensions::EXT::texture_filter_anisotropic>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::KHR::debug, + Extensions::EXT::texture_filter_anisotropic, + Extension>::value)); + + /* Empty variadic list should return true */ + CORRADE_VERIFY(Implementation::IsExtension<>::value); +} + void ContextTest::constructNoCreate() { { /* Shouldn't crash during construction, shouldn't attempt to access GL, From ab0568d4004e7345b1d21a75b44a47135c91e5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 11:17:38 +0100 Subject: [PATCH 018/161] GL: make compile-time extensions convertible to the Extension class. Will need this for supplying disabled extensions to Context configuration. --- src/Magnum/GL/Context.cpp | 689 +++++++++++++++++++------------------- src/Magnum/GL/Context.h | 5 +- 2 files changed, 351 insertions(+), 343 deletions(-) diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 4c825c516..7a438e941 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -72,455 +72,464 @@ using namespace Containers::Literals; to be sorted alphabetically. */ namespace { -#define _extension(vendor, extension) \ - {Extensions::vendor::extension::Index, Extensions::vendor::extension::requiredVersion(), Extensions::vendor::extension::coreVersion(), Extensions::vendor::extension::string()} #ifndef MAGNUM_TARGET_GLES constexpr Extension ExtensionList[]{ - _extension(AMD,sample_positions), - _extension(AMD,shader_explicit_vertex_parameter), - _extension(AMD,shader_trinary_minmax), - _extension(AMD,transform_feedback3_lines_triangles), - _extension(AMD,vertex_shader_layer), - _extension(ARB,ES3_2_compatibility), - _extension(ARB,bindless_texture), - _extension(ARB,compute_variable_group_size), - _extension(ARB,robustness), - _extension(ARB,robustness_application_isolation), - _extension(ARB,robustness_isolation), - _extension(ARB,robustness_share_group_isolation), - _extension(ARB,sample_locations), - _extension(ARB,seamless_cubemap_per_texture), - _extension(ARB,sparse_buffer), - _extension(ARB,sparse_texture), - _extension(ATI,texture_mirror_once), - _extension(EXT,debug_label), - _extension(EXT,debug_marker), - _extension(EXT,shader_integer_mix), - _extension(EXT,texture_compression_dxt1), - _extension(EXT,texture_compression_s3tc), - _extension(EXT,texture_filter_anisotropic), - _extension(EXT,texture_mirror_clamp), - _extension(EXT,texture_sRGB_R8), - _extension(EXT,texture_sRGB_decode), - _extension(GREMEDY,string_marker), - _extension(KHR,blend_equation_advanced), - _extension(KHR,blend_equation_advanced_coherent), - _extension(KHR,texture_compression_astc_hdr), - _extension(KHR,texture_compression_astc_ldr), - _extension(KHR,texture_compression_astc_sliced_3d), - _extension(NV,fragment_shader_barycentric), - _extension(NV,sample_locations), - _extension(OVR,multiview), - _extension(OVR,multiview2)}; + Extensions::AMD::sample_positions{}, + Extensions::AMD::shader_explicit_vertex_parameter{}, + Extensions::AMD::shader_trinary_minmax{}, + Extensions::AMD::transform_feedback3_lines_triangles{}, + Extensions::AMD::vertex_shader_layer{}, + Extensions::ARB::ES3_2_compatibility{}, + Extensions::ARB::bindless_texture{}, + Extensions::ARB::compute_variable_group_size{}, + Extensions::ARB::robustness{}, + Extensions::ARB::robustness_application_isolation{}, + Extensions::ARB::robustness_isolation{}, + Extensions::ARB::robustness_share_group_isolation{}, + Extensions::ARB::sample_locations{}, + Extensions::ARB::seamless_cubemap_per_texture{}, + Extensions::ARB::sparse_buffer{}, + Extensions::ARB::sparse_texture{}, + Extensions::ATI::texture_mirror_once{}, + Extensions::EXT::debug_label{}, + Extensions::EXT::debug_marker{}, + Extensions::EXT::shader_integer_mix{}, + Extensions::EXT::texture_compression_dxt1{}, + Extensions::EXT::texture_compression_s3tc{}, + Extensions::EXT::texture_filter_anisotropic{}, + Extensions::EXT::texture_mirror_clamp{}, + Extensions::EXT::texture_sRGB_R8{}, + Extensions::EXT::texture_sRGB_decode{}, + Extensions::GREMEDY::string_marker{}, + Extensions::KHR::blend_equation_advanced{}, + Extensions::KHR::blend_equation_advanced_coherent{}, + Extensions::KHR::texture_compression_astc_hdr{}, + Extensions::KHR::texture_compression_astc_ldr{}, + Extensions::KHR::texture_compression_astc_sliced_3d{}, + Extensions::NV::fragment_shader_barycentric{}, + Extensions::NV::sample_locations{}, + Extensions::OVR::multiview{}, + Extensions::OVR::multiview2{} +}; constexpr Extension ExtensionList300[]{ - _extension(ARB,color_buffer_float), - _extension(ARB,depth_buffer_float), - _extension(ARB,framebuffer_object), - _extension(ARB,framebuffer_sRGB), - _extension(ARB,half_float_pixel), - _extension(ARB,half_float_vertex), - _extension(ARB,map_buffer_range), - _extension(ARB,texture_float), - _extension(ARB,texture_rg), - _extension(ARB,vertex_array_object), - _extension(EXT,draw_buffers2), - _extension(EXT,gpu_shader4), - _extension(EXT,packed_float), - _extension(EXT,texture_array), - _extension(EXT,texture_compression_rgtc), - _extension(EXT,texture_integer), - _extension(EXT,texture_shared_exponent), - _extension(EXT,transform_feedback), - _extension(MAGNUM,shader_vertex_id), - _extension(NV,conditional_render), - _extension(NV,depth_buffer_float)}; + Extensions::ARB::color_buffer_float{}, + Extensions::ARB::depth_buffer_float{}, + Extensions::ARB::framebuffer_object{}, + Extensions::ARB::framebuffer_sRGB{}, + Extensions::ARB::half_float_pixel{}, + Extensions::ARB::half_float_vertex{}, + Extensions::ARB::map_buffer_range{}, + Extensions::ARB::texture_float{}, + Extensions::ARB::texture_rg{}, + Extensions::ARB::vertex_array_object{}, + Extensions::EXT::draw_buffers2{}, + Extensions::EXT::gpu_shader4{}, + Extensions::EXT::packed_float{}, + Extensions::EXT::texture_array{}, + Extensions::EXT::texture_compression_rgtc{}, + Extensions::EXT::texture_integer{}, + Extensions::EXT::texture_shared_exponent{}, + Extensions::EXT::transform_feedback{}, + Extensions::MAGNUM::shader_vertex_id{}, + Extensions::NV::conditional_render{}, + Extensions::NV::depth_buffer_float{} +}; constexpr Extension ExtensionList310[]{ - _extension(ARB,copy_buffer), - _extension(ARB,draw_instanced), - _extension(ARB,texture_buffer_object), - _extension(ARB,texture_rectangle), - _extension(ARB,uniform_buffer_object), - _extension(EXT,texture_snorm), - _extension(NV,primitive_restart)}; + Extensions::ARB::copy_buffer{}, + Extensions::ARB::draw_instanced{}, + Extensions::ARB::texture_buffer_object{}, + Extensions::ARB::texture_rectangle{}, + Extensions::ARB::uniform_buffer_object{}, + Extensions::EXT::texture_snorm{}, + Extensions::NV::primitive_restart{} +}; constexpr Extension ExtensionList320[]{ - _extension(ARB,depth_clamp), - _extension(ARB,draw_elements_base_vertex), - _extension(ARB,fragment_coord_conventions), - _extension(ARB,geometry_shader4), - _extension(ARB,provoking_vertex), - _extension(ARB,seamless_cube_map), - _extension(ARB,sync), - _extension(ARB,texture_multisample), - _extension(ARB,vertex_array_bgra)}; + Extensions::ARB::depth_clamp{}, + Extensions::ARB::draw_elements_base_vertex{}, + Extensions::ARB::fragment_coord_conventions{}, + Extensions::ARB::geometry_shader4{}, + Extensions::ARB::provoking_vertex{}, + Extensions::ARB::seamless_cube_map{}, + Extensions::ARB::sync{}, + Extensions::ARB::texture_multisample{}, + Extensions::ARB::vertex_array_bgra{} +}; constexpr Extension ExtensionList330[]{ - _extension(ARB,blend_func_extended), - _extension(ARB,explicit_attrib_location), - _extension(ARB,instanced_arrays), - _extension(ARB,occlusion_query2), - _extension(ARB,sampler_objects), - _extension(ARB,shader_bit_encoding), - _extension(ARB,texture_rgb10_a2ui), - _extension(ARB,texture_swizzle), - _extension(ARB,timer_query), - _extension(ARB,vertex_type_2_10_10_10_rev)}; + Extensions::ARB::blend_func_extended{}, + Extensions::ARB::explicit_attrib_location{}, + Extensions::ARB::instanced_arrays{}, + Extensions::ARB::occlusion_query2{}, + Extensions::ARB::sampler_objects{}, + Extensions::ARB::shader_bit_encoding{}, + Extensions::ARB::texture_rgb10_a2ui{}, + Extensions::ARB::texture_swizzle{}, + Extensions::ARB::timer_query{}, + Extensions::ARB::vertex_type_2_10_10_10_rev{} +}; constexpr Extension ExtensionList400[]{ - _extension(ARB,draw_buffers_blend), - _extension(ARB,draw_indirect), - _extension(ARB,gpu_shader5), - _extension(ARB,gpu_shader_fp64), - _extension(ARB,sample_shading), - _extension(ARB,shader_subroutine), - _extension(ARB,tessellation_shader), - _extension(ARB,texture_buffer_object_rgb32), - _extension(ARB,texture_cube_map_array), - _extension(ARB,texture_gather), - _extension(ARB,texture_query_lod), - _extension(ARB,transform_feedback2), - _extension(ARB,transform_feedback3)}; + Extensions::ARB::draw_buffers_blend{}, + Extensions::ARB::draw_indirect{}, + Extensions::ARB::gpu_shader5{}, + Extensions::ARB::gpu_shader_fp64{}, + Extensions::ARB::sample_shading{}, + Extensions::ARB::shader_subroutine{}, + Extensions::ARB::tessellation_shader{}, + Extensions::ARB::texture_buffer_object_rgb32{}, + Extensions::ARB::texture_cube_map_array{}, + Extensions::ARB::texture_gather{}, + Extensions::ARB::texture_query_lod{}, + Extensions::ARB::transform_feedback2{}, + Extensions::ARB::transform_feedback3{} +}; constexpr Extension ExtensionList410[]{ - _extension(ARB,ES2_compatibility), - _extension(ARB,get_program_binary), - _extension(ARB,separate_shader_objects), - _extension(ARB,shader_precision), - _extension(ARB,vertex_attrib_64bit), - _extension(ARB,viewport_array)}; + Extensions::ARB::ES2_compatibility{}, + Extensions::ARB::get_program_binary{}, + Extensions::ARB::separate_shader_objects{}, + Extensions::ARB::shader_precision{}, + Extensions::ARB::vertex_attrib_64bit{}, + Extensions::ARB::viewport_array{} +}; constexpr Extension ExtensionList420[]{ - _extension(ARB,base_instance), - _extension(ARB,compressed_texture_pixel_storage), - _extension(ARB,conservative_depth), - _extension(ARB,internalformat_query), - _extension(ARB,map_buffer_alignment), - _extension(ARB,shader_atomic_counters), - _extension(ARB,shader_image_load_store), - _extension(ARB,shading_language_420pack), + Extensions::ARB::base_instance{}, + Extensions::ARB::compressed_texture_pixel_storage{}, + Extensions::ARB::conservative_depth{}, + Extensions::ARB::internalformat_query{}, + Extensions::ARB::map_buffer_alignment{}, + Extensions::ARB::shader_atomic_counters{}, + Extensions::ARB::shader_image_load_store{}, + Extensions::ARB::shading_language_420pack{}, /* Mentioned in GLSL 4.20 specs as newly added */ - _extension(ARB,shading_language_packing), - _extension(ARB,texture_compression_bptc), - _extension(ARB,texture_storage), - _extension(ARB,transform_feedback_instanced)}; + Extensions::ARB::shading_language_packing{}, + Extensions::ARB::texture_compression_bptc{}, + Extensions::ARB::texture_storage{}, + Extensions::ARB::transform_feedback_instanced{} +}; constexpr Extension ExtensionList430[]{ - _extension(ARB,ES3_compatibility), - _extension(ARB,arrays_of_arrays), - _extension(ARB,clear_buffer_object), - _extension(ARB,compute_shader), - _extension(ARB,copy_image), - _extension(ARB,explicit_uniform_location), - _extension(ARB,fragment_layer_viewport), - _extension(ARB,framebuffer_no_attachments), - _extension(ARB,internalformat_query2), - _extension(ARB,invalidate_subdata), - _extension(ARB,multi_draw_indirect), - _extension(ARB,program_interface_query), - _extension(ARB,robust_buffer_access_behavior), - _extension(ARB,shader_image_size), - _extension(ARB,shader_storage_buffer_object), - _extension(ARB,stencil_texturing), - _extension(ARB,texture_buffer_range), - _extension(ARB,texture_query_levels), - _extension(ARB,texture_storage_multisample), - _extension(ARB,texture_view), - _extension(ARB,vertex_attrib_binding), - _extension(KHR,debug)}; + Extensions::ARB::ES3_compatibility{}, + Extensions::ARB::arrays_of_arrays{}, + Extensions::ARB::clear_buffer_object{}, + Extensions::ARB::compute_shader{}, + Extensions::ARB::copy_image{}, + Extensions::ARB::explicit_uniform_location{}, + Extensions::ARB::fragment_layer_viewport{}, + Extensions::ARB::framebuffer_no_attachments{}, + Extensions::ARB::internalformat_query2{}, + Extensions::ARB::invalidate_subdata{}, + Extensions::ARB::multi_draw_indirect{}, + Extensions::ARB::program_interface_query{}, + Extensions::ARB::robust_buffer_access_behavior{}, + Extensions::ARB::shader_image_size{}, + Extensions::ARB::shader_storage_buffer_object{}, + Extensions::ARB::stencil_texturing{}, + Extensions::ARB::texture_buffer_range{}, + Extensions::ARB::texture_query_levels{}, + Extensions::ARB::texture_storage_multisample{}, + Extensions::ARB::texture_view{}, + Extensions::ARB::vertex_attrib_binding{}, + Extensions::KHR::debug{} +}; constexpr Extension ExtensionList440[]{ - _extension(ARB,buffer_storage), - _extension(ARB,clear_texture), - _extension(ARB,enhanced_layouts), - _extension(ARB,multi_bind), - _extension(ARB,query_buffer_object), - _extension(ARB,texture_mirror_clamp_to_edge), - _extension(ARB,texture_stencil8), - _extension(ARB,vertex_type_10f_11f_11f_rev)}; + Extensions::ARB::buffer_storage{}, + Extensions::ARB::clear_texture{}, + Extensions::ARB::enhanced_layouts{}, + Extensions::ARB::multi_bind{}, + Extensions::ARB::query_buffer_object{}, + Extensions::ARB::texture_mirror_clamp_to_edge{}, + Extensions::ARB::texture_stencil8{}, + Extensions::ARB::vertex_type_10f_11f_11f_rev{} +}; constexpr Extension ExtensionList450[]{ - _extension(ARB,ES3_1_compatibility), - _extension(ARB,clip_control), - _extension(ARB,conditional_render_inverted), - _extension(ARB,cull_distance), - _extension(ARB,derivative_control), - _extension(ARB,direct_state_access), - _extension(ARB,get_texture_sub_image), - _extension(ARB,shader_texture_image_samples), - _extension(ARB,texture_barrier), - _extension(KHR,context_flush_control), - _extension(KHR,robustness)}; + Extensions::ARB::ES3_1_compatibility{}, + Extensions::ARB::clip_control{}, + Extensions::ARB::conditional_render_inverted{}, + Extensions::ARB::cull_distance{}, + Extensions::ARB::derivative_control{}, + Extensions::ARB::direct_state_access{}, + Extensions::ARB::get_texture_sub_image{}, + Extensions::ARB::shader_texture_image_samples{}, + Extensions::ARB::texture_barrier{}, + Extensions::KHR::context_flush_control{}, + Extensions::KHR::robustness{} +}; constexpr Extension ExtensionList460[]{ - _extension(ARB,gl_spirv), - _extension(ARB,indirect_parameters), - _extension(ARB,pipeline_statistics_query), - _extension(ARB,polygon_offset_clamp), - _extension(ARB,shader_atomic_counter_ops), - _extension(ARB,shader_draw_parameters), - _extension(ARB,shader_group_vote), - _extension(ARB,spirv_extensions), - _extension(ARB,texture_filter_anisotropic), - _extension(ARB,transform_feedback_overflow_query), - _extension(KHR,no_error)}; + Extensions::ARB::gl_spirv{}, + Extensions::ARB::indirect_parameters{}, + Extensions::ARB::pipeline_statistics_query{}, + Extensions::ARB::polygon_offset_clamp{}, + Extensions::ARB::shader_atomic_counter_ops{}, + Extensions::ARB::shader_draw_parameters{}, + Extensions::ARB::shader_group_vote{}, + Extensions::ARB::spirv_extensions{}, + Extensions::ARB::texture_filter_anisotropic{}, + Extensions::ARB::transform_feedback_overflow_query{}, + Extensions::KHR::no_error{} +}; #elif defined(MAGNUM_TARGET_WEBGL) constexpr Extension ExtensionList[]{ #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,clip_cull_distance), + Extensions::EXT::clip_cull_distance{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,color_buffer_float), + Extensions::EXT::color_buffer_float{}, #endif #ifdef MAGNUM_TARGET_GLES2 - _extension(EXT,disjoint_timer_query), + Extensions::EXT::disjoint_timer_query{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,disjoint_timer_query_webgl2), + Extensions::EXT::disjoint_timer_query_webgl2{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,draw_buffers_indexed), + Extensions::EXT::draw_buffers_indexed{}, #endif - _extension(EXT,float_blend), - _extension(EXT,texture_compression_bptc), - _extension(EXT,texture_compression_rgtc), - _extension(EXT,texture_filter_anisotropic), - _extension(EXT,texture_norm16), - _extension(OES,texture_float_linear), + Extensions::EXT::float_blend{}, + Extensions::EXT::texture_compression_bptc{}, + Extensions::EXT::texture_compression_rgtc{}, + Extensions::EXT::texture_filter_anisotropic{}, + Extensions::EXT::texture_norm16{}, + Extensions::OES::texture_float_linear{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(OVR,multiview2), + Extensions::OVR::multiview2{}, #endif - _extension(WEBGL,blend_equation_advanced_coherent), - _extension(WEBGL,compressed_texture_astc), - _extension(WEBGL,compressed_texture_pvrtc), - _extension(WEBGL,compressed_texture_s3tc), - _extension(WEBGL,compressed_texture_s3tc_srgb), - _extension(WEBGL,debug_renderer_info), - _extension(WEBGL,debug_shaders), + Extensions::WEBGL::blend_equation_advanced_coherent{}, + Extensions::WEBGL::compressed_texture_astc{}, + Extensions::WEBGL::compressed_texture_pvrtc{}, + Extensions::WEBGL::compressed_texture_s3tc{}, + Extensions::WEBGL::compressed_texture_s3tc_srgb{}, + Extensions::WEBGL::debug_renderer_info{}, + Extensions::WEBGL::debug_shaders{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(WEBGL,draw_instanced_base_vertex_base_instance), + Extensions::WEBGL::draw_instanced_base_vertex_base_instance{}, #endif - _extension(WEBGL,lose_context), - _extension(WEBGL,multi_draw), + Extensions::WEBGL::lose_context{}, + Extensions::WEBGL::multi_draw{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(WEBGL,multi_draw_instanced_base_vertex_base_instance) + Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance{}, #endif }; constexpr Extension ExtensionListES300[]{ #ifdef MAGNUM_TARGET_GLES2 - _extension(ANGLE,instanced_arrays), - _extension(EXT,blend_minmax), - _extension(EXT,color_buffer_half_float), - _extension(EXT,frag_depth), - _extension(EXT,sRGB), - _extension(EXT,shader_texture_lod), + Extensions::ANGLE::instanced_arrays{}, + Extensions::EXT::blend_minmax{}, + Extensions::EXT::color_buffer_half_float{}, + Extensions::EXT::frag_depth{}, + Extensions::EXT::sRGB{}, + Extensions::EXT::shader_texture_lod{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(MAGNUM,shader_vertex_id), + Extensions::MAGNUM::shader_vertex_id{}, #endif #ifdef MAGNUM_TARGET_GLES2 - _extension(OES,element_index_uint), - _extension(OES,fbo_render_mipmap), - _extension(OES,standard_derivatives), - _extension(OES,texture_float), - _extension(OES,texture_half_float), - _extension(OES,texture_half_float_linear), - _extension(OES,vertex_array_object), - _extension(WEBGL,color_buffer_float), - _extension(WEBGL,depth_texture), - _extension(WEBGL,draw_buffers) + Extensions::OES::element_index_uint{}, + Extensions::OES::fbo_render_mipmap{}, + Extensions::OES::standard_derivatives{}, + Extensions::OES::texture_float{}, + Extensions::OES::texture_half_float{}, + Extensions::OES::texture_half_float_linear{}, + Extensions::OES::vertex_array_object{}, + Extensions::WEBGL::color_buffer_float{}, + Extensions::WEBGL::depth_texture{}, + Extensions::WEBGL::draw_buffers{}, #endif }; #else constexpr Extension ExtensionList[]{ #ifndef MAGNUM_TARGET_GLES2 - _extension(ANDROID,extension_pack_es31a), + Extensions::ANDROID::extension_pack_es31a{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(ANGLE,base_vertex_base_instance), + Extensions::ANGLE::base_vertex_base_instance{}, #endif - _extension(ANGLE,multi_draw), - _extension(ANGLE,texture_compression_dxt1), - _extension(ANGLE,texture_compression_dxt3), - _extension(ANGLE,texture_compression_dxt5), - _extension(APPLE,clip_distance), - _extension(APPLE,texture_format_BGRA8888), - _extension(ARM,shader_framebuffer_fetch), - _extension(ARM,shader_framebuffer_fetch_depth_stencil), + Extensions::ANGLE::multi_draw{}, + Extensions::ANGLE::texture_compression_dxt1{}, + Extensions::ANGLE::texture_compression_dxt3{}, + Extensions::ANGLE::texture_compression_dxt5{}, + Extensions::APPLE::clip_distance{}, + Extensions::APPLE::texture_format_BGRA8888{}, + Extensions::ARM::shader_framebuffer_fetch{}, + Extensions::ARM::shader_framebuffer_fetch_depth_stencil{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,clip_cull_distance), + Extensions::EXT::clip_cull_distance{}, #endif - _extension(EXT,debug_label), - _extension(EXT,debug_marker), - _extension(EXT,disjoint_timer_query), - _extension(EXT,draw_elements_base_vertex), - _extension(EXT,multi_draw_arrays), - _extension(EXT,multisampled_render_to_texture), - _extension(EXT,polygon_offset_clamp), - _extension(EXT,pvrtc_sRGB), - _extension(EXT,read_format_bgra), - _extension(EXT,robustness), - _extension(EXT,sRGB_write_control), - _extension(EXT,separate_shader_objects), - _extension(EXT,shader_framebuffer_fetch), + Extensions::EXT::debug_label{}, + Extensions::EXT::debug_marker{}, + Extensions::EXT::disjoint_timer_query{}, + Extensions::EXT::draw_elements_base_vertex{}, + Extensions::EXT::multi_draw_arrays{}, + Extensions::EXT::multisampled_render_to_texture{}, + Extensions::EXT::polygon_offset_clamp{}, + Extensions::EXT::pvrtc_sRGB{}, + Extensions::EXT::read_format_bgra{}, + Extensions::EXT::robustness{}, + Extensions::EXT::sRGB_write_control{}, + Extensions::EXT::separate_shader_objects{}, + Extensions::EXT::shader_framebuffer_fetch{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,shader_integer_mix), + Extensions::EXT::shader_integer_mix{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,texture_compression_bptc), + Extensions::EXT::texture_compression_bptc{}, #endif - _extension(EXT,texture_compression_dxt1), + Extensions::EXT::texture_compression_dxt1{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,texture_compression_rgtc), + Extensions::EXT::texture_compression_rgtc{}, #endif - _extension(EXT,texture_compression_s3tc), - _extension(EXT,texture_compression_s3tc_srgb), - _extension(EXT,texture_filter_anisotropic), - _extension(EXT,texture_format_BGRA8888), + Extensions::EXT::texture_compression_s3tc{}, + Extensions::EXT::texture_compression_s3tc_srgb{}, + Extensions::EXT::texture_filter_anisotropic{}, + Extensions::EXT::texture_format_BGRA8888{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,texture_norm16), - _extension(EXT,texture_sRGB_R8), + Extensions::EXT::texture_norm16{}, + Extensions::EXT::texture_sRGB_R8{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,texture_sRGB_RG8), + Extensions::EXT::texture_sRGB_RG8{}, #endif - _extension(EXT,texture_sRGB_decode), - _extension(IMG,texture_compression_pvrtc), - _extension(KHR,blend_equation_advanced_coherent), - _extension(KHR,context_flush_control), - _extension(KHR,no_error), - _extension(KHR,texture_compression_astc_hdr), - _extension(KHR,texture_compression_astc_sliced_3d), + Extensions::EXT::texture_sRGB_decode{}, + Extensions::IMG::texture_compression_pvrtc{}, + Extensions::KHR::blend_equation_advanced_coherent{}, + Extensions::KHR::context_flush_control{}, + Extensions::KHR::no_error{}, + Extensions::KHR::texture_compression_astc_hdr{}, + Extensions::KHR::texture_compression_astc_sliced_3d{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(NV,fragment_shader_barycentric), + Extensions::NV::fragment_shader_barycentric{}, #endif - _extension(NV,polygon_mode), - _extension(NV,read_buffer_front), - _extension(NV,read_depth), - _extension(NV,read_depth_stencil), - _extension(NV,read_stencil), - _extension(NV,sample_locations), + Extensions::NV::polygon_mode{}, + Extensions::NV::read_buffer_front{}, + Extensions::NV::read_depth{}, + Extensions::NV::read_depth_stencil{}, + Extensions::NV::read_stencil{}, + Extensions::NV::sample_locations{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(NV,shader_noperspective_interpolation), + Extensions::NV::shader_noperspective_interpolation{}, #endif - _extension(NV,texture_border_clamp), - _extension(OES,depth32), - _extension(OES,draw_elements_base_vertex), - _extension(OES,mapbuffer), - _extension(OES,stencil1), - _extension(OES,stencil4), + Extensions::NV::texture_border_clamp{}, + Extensions::OES::depth32{}, + Extensions::OES::draw_elements_base_vertex{}, + Extensions::OES::mapbuffer{}, + Extensions::OES::stencil1{}, + Extensions::OES::stencil4{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(OES,texture_compression_astc), + Extensions::OES::texture_compression_astc{}, #endif - _extension(OES,texture_float_linear), + Extensions::OES::texture_float_linear{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(OVR,multiview), + Extensions::OVR::multiview{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(OVR,multiview2), + Extensions::OVR::multiview2{}, #endif }; constexpr Extension ExtensionListES300[]{ #ifdef MAGNUM_TARGET_GLES2 - _extension(ANGLE,depth_texture), - _extension(ANGLE,framebuffer_blit), - _extension(ANGLE,framebuffer_multisample), - _extension(ANGLE,instanced_arrays), - _extension(APPLE,framebuffer_multisample), - _extension(APPLE,texture_max_level), - _extension(ARM,rgba8), - _extension(EXT,blend_minmax), - _extension(EXT,discard_framebuffer), - _extension(EXT,draw_buffers), - _extension(EXT,draw_instanced), - _extension(EXT,instanced_arrays), - _extension(EXT,map_buffer_range), - _extension(EXT,occlusion_query_boolean), - _extension(EXT,sRGB), - _extension(EXT,shader_texture_lod), - _extension(EXT,shadow_samplers), - _extension(EXT,texture_rg), - _extension(EXT,texture_storage), - _extension(EXT,texture_type_2_10_10_10_REV), - _extension(EXT,unpack_subimage), + Extensions::ANGLE::depth_texture{}, + Extensions::ANGLE::framebuffer_blit{}, + Extensions::ANGLE::framebuffer_multisample{}, + Extensions::ANGLE::instanced_arrays{}, + Extensions::APPLE::framebuffer_multisample{}, + Extensions::APPLE::texture_max_level{}, + Extensions::ARM::rgba8{}, + Extensions::EXT::blend_minmax{}, + Extensions::EXT::discard_framebuffer{}, + Extensions::EXT::draw_buffers{}, + Extensions::EXT::draw_instanced{}, + Extensions::EXT::instanced_arrays{}, + Extensions::EXT::map_buffer_range{}, + Extensions::EXT::occlusion_query_boolean{}, + Extensions::EXT::sRGB{}, + Extensions::EXT::shader_texture_lod{}, + Extensions::EXT::shadow_samplers{}, + Extensions::EXT::texture_rg{}, + Extensions::EXT::texture_storage{}, + Extensions::EXT::texture_type_2_10_10_10_REV{}, + Extensions::EXT::unpack_subimage{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(MAGNUM,shader_vertex_id), + Extensions::MAGNUM::shader_vertex_id{}, #endif #ifdef MAGNUM_TARGET_GLES2 - _extension(NV,draw_buffers), - _extension(NV,draw_instanced), - _extension(NV,fbo_color_attachments), - _extension(NV,framebuffer_blit), - _extension(NV,framebuffer_multisample), - _extension(NV,instanced_arrays), - _extension(NV,pack_subimage), - _extension(NV,read_buffer), - _extension(NV,shadow_samplers_array), - _extension(NV,shadow_samplers_cube), - _extension(OES,depth24), - _extension(OES,depth_texture), - _extension(OES,element_index_uint), - _extension(OES,fbo_render_mipmap), - _extension(OES,packed_depth_stencil), - _extension(OES,required_internalformat), - _extension(OES,rgb8_rgba8), - _extension(OES,standard_derivatives), - _extension(OES,surfaceless_context), - _extension(OES,texture_3D), - _extension(OES,texture_float), - _extension(OES,texture_half_float), - _extension(OES,texture_half_float_linear), - _extension(OES,texture_npot), - _extension(OES,vertex_array_object), - _extension(OES,vertex_half_float), + Extensions::NV::draw_buffers{}, + Extensions::NV::draw_instanced{}, + Extensions::NV::fbo_color_attachments{}, + Extensions::NV::framebuffer_blit{}, + Extensions::NV::framebuffer_multisample{}, + Extensions::NV::instanced_arrays{}, + Extensions::NV::pack_subimage{}, + Extensions::NV::read_buffer{}, + Extensions::NV::shadow_samplers_array{}, + Extensions::NV::shadow_samplers_cube{}, + Extensions::OES::depth24{}, + Extensions::OES::depth_texture{}, + Extensions::OES::element_index_uint{}, + Extensions::OES::fbo_render_mipmap{}, + Extensions::OES::packed_depth_stencil{}, + Extensions::OES::required_internalformat{}, + Extensions::OES::rgb8_rgba8{}, + Extensions::OES::standard_derivatives{}, + Extensions::OES::surfaceless_context{}, + Extensions::OES::texture_3D{}, + Extensions::OES::texture_float{}, + Extensions::OES::texture_half_float{}, + Extensions::OES::texture_half_float_linear{}, + Extensions::OES::texture_npot{}, + Extensions::OES::vertex_array_object{}, + Extensions::OES::vertex_half_float{}, #endif }; constexpr Extension ExtensionListES320[]{ #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,color_buffer_float), + Extensions::EXT::color_buffer_float{}, #endif - _extension(EXT,color_buffer_half_float), + Extensions::EXT::color_buffer_half_float{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,copy_image), + Extensions::EXT::copy_image{}, #endif - _extension(EXT,draw_buffers_indexed), + Extensions::EXT::draw_buffers_indexed{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,geometry_shader), + Extensions::EXT::geometry_shader{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,gpu_shader5), + Extensions::EXT::gpu_shader5{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,primitive_bounding_box), + Extensions::EXT::primitive_bounding_box{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,shader_io_blocks), + Extensions::EXT::shader_io_blocks{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,tessellation_shader), + Extensions::EXT::tessellation_shader{}, #endif - _extension(EXT,texture_border_clamp), + Extensions::EXT::texture_border_clamp{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,texture_buffer), + Extensions::EXT::texture_buffer{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(EXT,texture_cube_map_array), + Extensions::EXT::texture_cube_map_array{}, #endif - _extension(KHR,blend_equation_advanced), - _extension(KHR,debug), - _extension(KHR,robust_buffer_access_behavior), - _extension(KHR,robustness), - _extension(KHR,texture_compression_astc_ldr), + Extensions::KHR::blend_equation_advanced{}, + Extensions::KHR::debug{}, + Extensions::KHR::robust_buffer_access_behavior{}, + Extensions::KHR::robustness{}, + Extensions::KHR::texture_compression_astc_ldr{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(OES,sample_shading), + Extensions::OES::sample_shading{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(OES,sample_variables), + Extensions::OES::sample_variables{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(OES,shader_image_atomic), + Extensions::OES::shader_image_atomic{}, #endif #ifndef MAGNUM_TARGET_GLES2 - _extension(OES,shader_multisample_interpolation), + Extensions::OES::shader_multisample_interpolation{}, #endif - _extension(OES,texture_stencil8), + Extensions::OES::texture_stencil8{}, #ifndef MAGNUM_TARGET_GLES2 - _extension(OES,texture_storage_multisample_2d_array) + Extensions::OES::texture_storage_multisample_2d_array{} #endif }; #endif -#undef _extension constexpr struct { Version version; diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 45bb43794..c776bee92 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -94,9 +94,8 @@ class MAGNUM_GL_EXPORT Extension { /** @brief Extension string */ constexpr const char* string() const { return _string; } - #ifndef DOXYGEN_GENERATING_OUTPUT - constexpr Extension(std::size_t index, Version requiredVersion, Version coreVersion, const char* string): _index{index}, _requiredVersion{requiredVersion}, _coreVersion{coreVersion}, _string{string} {} - #endif + /** @brief Construct from a compile-time extension */ + template::value>::type> constexpr /*implicit*/ Extension(const E&): _index{E::Index}, _requiredVersion{E::requiredVersion()}, _coreVersion{E::coreVersion()}, _string{E::string()} {} private: std::size_t _index; From 93fa1b9f943a15f8919cc9c9ed10ccc7b129a062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 20:26:25 +0100 Subject: [PATCH 019/161] GL: EXT_texture_norm16 is not on WebGL 1 anymore. It got changed shortly after the original implementation in 083ecf72b8a3de8b92cd2df2a597722a636c19da to be WebGL 2 only. --- src/Magnum/GL/AbstractTexture.cpp | 20 +++----------- src/Magnum/GL/Context.cpp | 2 ++ src/Magnum/GL/Extensions.h | 2 +- .../GL/Implementation/pixelFormatMapping.hpp | 8 +----- src/Magnum/GL/PixelFormat.cpp | 6 ++--- src/Magnum/GL/PixelFormat.h | 14 +++++----- src/Magnum/GL/RenderbufferFormat.h | 21 +++++++++------ src/Magnum/GL/TextureFormat.cpp | 2 +- src/Magnum/GL/TextureFormat.h | 27 ++++++++++++------- .../OpenGL/GLES2/Emscripten/extensions.txt | 1 - .../OpenGL/GLES2/flextGLEmscripten.h | 11 -------- 11 files changed, 49 insertions(+), 65 deletions(-) diff --git a/src/Magnum/GL/AbstractTexture.cpp b/src/Magnum/GL/AbstractTexture.cpp index 275035e57..24fc8f128 100644 --- a/src/Magnum/GL/AbstractTexture.cpp +++ b/src/Magnum/GL/AbstractTexture.cpp @@ -662,8 +662,7 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) { #ifndef MAGNUM_TARGET_GLES2 case TextureFormat::RGB8Snorm: #endif - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 case TextureFormat::RGB16: case TextureFormat::RGB16Snorm: #endif @@ -741,8 +740,7 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) { #ifndef MAGNUM_TARGET_GLES2 case TextureFormat::RGBA8Snorm: #endif - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 case TextureFormat::RGBA16: case TextureFormat::RGBA16Snorm: #endif @@ -853,16 +851,8 @@ PixelFormat pixelFormatForInternalFormat(const TextureFormat internalFormat) { #ifdef MAGNUM_TARGET_GLES2 case TextureFormat::Luminance: - #ifdef MAGNUM_TARGET_WEBGL - case TextureFormat::R16: - case TextureFormat::R16Snorm: - #endif return PixelFormat::Luminance; case TextureFormat::LuminanceAlpha: - #ifdef MAGNUM_TARGET_WEBGL - case TextureFormat::RG16: - case TextureFormat::RG16Snorm: - #endif return PixelFormat::LuminanceAlpha; #endif @@ -1058,8 +1048,7 @@ PixelType pixelTypeForInternalFormat(const TextureFormat internalFormat) { #endif #endif - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 case TextureFormat::R16: case TextureFormat::RG16: case TextureFormat::RGB16: @@ -1080,8 +1069,7 @@ PixelType pixelTypeForInternalFormat(const TextureFormat internalFormat) { #endif return PixelType::UnsignedShort; - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 case TextureFormat::R16Snorm: case TextureFormat::RG16Snorm: case TextureFormat::RGB16Snorm: diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 7a438e941..e47604bf6 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -285,7 +285,9 @@ constexpr Extension ExtensionList[]{ Extensions::EXT::texture_compression_bptc{}, Extensions::EXT::texture_compression_rgtc{}, Extensions::EXT::texture_filter_anisotropic{}, + #ifndef MAGNUM_TARGET_GLES2 Extensions::EXT::texture_norm16{}, + #endif Extensions::OES::texture_float_linear{}, #ifndef MAGNUM_TARGET_GLES2 Extensions::OVR::multiview2{}, diff --git a/src/Magnum/GL/Extensions.h b/src/Magnum/GL/Extensions.h index b03b8e944..92db6ce13 100644 --- a/src/Magnum/GL/Extensions.h +++ b/src/Magnum/GL/Extensions.h @@ -301,8 +301,8 @@ namespace ANGLE { _extension(13,EXT,texture_compression_bptc, GLES200, None) // #39 #ifndef MAGNUM_TARGET_GLES2 _extension(14,EXT,clip_cull_distance, GLES300, None) // #43 + _extension(15,EXT,texture_norm16, GLES300, None) // #44 #endif - _extension(15,EXT,texture_norm16, GLES200, None) // #44 #ifndef MAGNUM_TARGET_GLES2 _extension(16,EXT,draw_buffers_indexed, GLES300, None) // #45 #endif diff --git a/src/Magnum/GL/Implementation/pixelFormatMapping.hpp b/src/Magnum/GL/Implementation/pixelFormatMapping.hpp index 37a8e22e3..0d487f6b4 100644 --- a/src/Magnum/GL/Implementation/pixelFormatMapping.hpp +++ b/src/Magnum/GL/Implementation/pixelFormatMapping.hpp @@ -115,17 +115,11 @@ _n(RG16Unorm, LuminanceAlpha, UnsignedShort) _n(RGB16Unorm, RGB, UnsignedShort) _n(RGBA16Unorm, RGBA, UnsignedShort) #endif -/* Available everywhere except ES2 (WebGL 1 has it) */ -#ifndef MAGNUM_TARGET_GLES2 +#ifndef MAGNUM_TARGET_GLES _c(R16Snorm, Red, Short, R16Snorm) _c(RG16Snorm, RG, Short, RG16Snorm) _c(RGB16Snorm, RGB, Short, RGB16Snorm) _c(RGBA16Snorm, RGBA, Short, RGBA16Snorm) -#elif defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL) -_c(R16Snorm, Luminance, Short, R16Snorm) -_c(RG16Snorm, LuminanceAlpha, Short, RG16Snorm) -_c(RGB16Snorm, RGB, Short, RGB16Snorm) -_c(RGBA16Snorm, RGBA, Short, RGBA16Snorm) #else _s(R16Snorm) _s(RG16Snorm) diff --git a/src/Magnum/GL/PixelFormat.cpp b/src/Magnum/GL/PixelFormat.cpp index e9bd60574..155629a41 100644 --- a/src/Magnum/GL/PixelFormat.cpp +++ b/src/Magnum/GL/PixelFormat.cpp @@ -135,8 +135,7 @@ UnsignedInt pixelSize(const PixelFormat format, const PixelType type) { #endif size = 1; break; case PixelType::UnsignedShort: - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 case PixelType::Short: #endif case PixelType::Half: @@ -345,8 +344,7 @@ Debug& operator<<(Debug& debug, const PixelType value) { _c(Byte) #endif _c(UnsignedShort) - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 _c(Short) #endif _c(UnsignedInt) diff --git a/src/Magnum/GL/PixelFormat.h b/src/Magnum/GL/PixelFormat.h index 8b3efb5f5..46c631f82 100644 --- a/src/Magnum/GL/PixelFormat.h +++ b/src/Magnum/GL/PixelFormat.h @@ -376,21 +376,23 @@ enum class PixelType: GLenum { * for color texture data * @requires_webgl20 Extension @webgl_extension{WEBGL,depth_texture} in * WebGL 1.0 for depth texture data - * @requires_webgl_extension @webgl_extension{EXT,texture_norm16} for color - * texture data + * @requires_webgl20 For integer color texture data + * @requires_webgl_extension WebGL 2.0 and + * @webgl_extension{EXT,texture_norm16} for normalized color texture + * data */ UnsignedShort = GL_UNSIGNED_SHORT, - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 /** * Each component signed short. * @requires_gl Can't be used for framebuffer reading in OpenGL ES or * WebGL. * @requires_gles30 For texture data only, only @ref PixelType::UnsignedShort * is available in OpenGL ES 2.0. - * @requires_webgl20 For texture data only, @webgl_extension{EXT,texture_norm16} - * in WebGL 1.0. + * @requires_webgl20 For integer texture data. Not available in WebGL 1.0. + * @requires_webgl_extension WebGL 2.0 and + * @webgl_extension{EXT,texture_norm16} for normalized texture data */ Short = GL_SHORT, #endif diff --git a/src/Magnum/GL/RenderbufferFormat.h b/src/Magnum/GL/RenderbufferFormat.h index 8b32b23ad..0d037d79c 100644 --- a/src/Magnum/GL/RenderbufferFormat.h +++ b/src/Magnum/GL/RenderbufferFormat.h @@ -125,16 +125,17 @@ enum class RenderbufferFormat: GLenum { #endif #endif - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 /** * Red component, normalized unsigned short. * @requires_gl30 Extension @gl_extension{ARB,texture_rg} * @requires_gles31 Only byte-sized normalized formats (such as * @ref RenderbufferFormat::RG8) are available in OpenGL ES 3.0 and * older; not defined on ES2 - * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES R16 = GL_R16, @@ -148,8 +149,10 @@ enum class RenderbufferFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats (such as * @ref RenderbufferFormat::RG8) are available in OpenGL ES 3.0 and * older; not defined on ES2 - * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES RG16 = GL_RG16, @@ -171,8 +174,10 @@ enum class RenderbufferFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats (such as * @ref RenderbufferFormat::RG8) are available in OpenGL ES 3.0 and * older; not defined on ES2 - * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_es_extension OpenGL ES 3.1 and extension + * @gl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES RGBA16 = GL_RGBA16, diff --git a/src/Magnum/GL/TextureFormat.cpp b/src/Magnum/GL/TextureFormat.cpp index 6d43e02e4..8ef426937 100644 --- a/src/Magnum/GL/TextureFormat.cpp +++ b/src/Magnum/GL/TextureFormat.cpp @@ -89,7 +89,7 @@ Debug& operator<<(Debug& debug, const TextureFormat value) { _c(RGB8Snorm) _c(RGBA8Snorm) #endif - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 _c(R16) _c(RG16) _c(RGB16) diff --git a/src/Magnum/GL/TextureFormat.h b/src/Magnum/GL/TextureFormat.h index a9638cf0a..623243ecf 100644 --- a/src/Magnum/GL/TextureFormat.h +++ b/src/Magnum/GL/TextureFormat.h @@ -335,15 +335,15 @@ enum class TextureFormat: GLenum { RGBA8Snorm = GL_RGBA8_SNORM, #endif - /* Available everywhere except ES2 (WebGL 1 has it) */ - #if !(defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)) + #ifndef MAGNUM_TARGET_GLES2 /** * Red component, normalized unsigned short. * @requires_gl30 Extension @gl_extension{ARB,texture_rg} * @requires_gles30 Only byte-sized normalized formats are available in * OpenGL ES 2.0 * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES R16 = GL_R16, @@ -357,7 +357,8 @@ enum class TextureFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats are available in * OpenGL ES 3.0 and older; not defined on ES2 * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES RG16 = GL_RG16, @@ -370,7 +371,8 @@ enum class TextureFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats are available in * OpenGL ES 3.0 and older; not defined on ES2 * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES RGB16 = GL_RGB16, @@ -383,7 +385,8 @@ enum class TextureFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats are available in * OpenGL ES 3.0 and older; not defined on ES2 * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES RGBA16 = GL_RGBA16, @@ -397,7 +400,8 @@ enum class TextureFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats are available in * OpenGL ES 3.0 and older; not defined on ES2 * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES R16Snorm = GL_R16_SNORM, @@ -411,7 +415,8 @@ enum class TextureFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats are available in * OpenGL ES 3.0 and older; not defined on ES2 * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES RG16Snorm = GL_RG16_SNORM, @@ -425,7 +430,8 @@ enum class TextureFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats are available in * OpenGL ES 3.0 and older; not defined on ES2 * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES RGB16Snorm = GL_RGB16_SNORM, @@ -439,7 +445,8 @@ enum class TextureFormat: GLenum { * @requires_gles31 Only byte-sized normalized formats are available in * OpenGL ES 3.0 and older; not defined on ES2 * @requires_es_extension OpenGL ES 3.1 and @gl_extension{EXT,texture_norm16} - * @requires_webgl_extension Extension @webgl_extension{EXT,texture_norm16} + * @requires_webgl_extension WebGL 2.0 and extension + * @webgl_extension{EXT,texture_norm16} */ #ifndef MAGNUM_TARGET_GLES RGBA16Snorm = GL_RGBA16_SNORM, diff --git a/src/MagnumExternal/OpenGL/GLES2/Emscripten/extensions.txt b/src/MagnumExternal/OpenGL/GLES2/Emscripten/extensions.txt index a95e95b8c..dfb959d2b 100644 --- a/src/MagnumExternal/OpenGL/GLES2/Emscripten/extensions.txt +++ b/src/MagnumExternal/OpenGL/GLES2/Emscripten/extensions.txt @@ -27,7 +27,6 @@ extension EXT_texture_filter_anisotropic optional extension EXT_disjoint_timer_query optional extension EXT_texture_compression_rgtc optional extension EXT_texture_compression_bptc optional -extension EXT_texture_norm16 optional # These are used as a base for WEBGL_* extensions extension EXT_color_buffer_float optional extension EXT_texture_compression_s3tc optional diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGLEmscripten.h b/src/MagnumExternal/OpenGL/GLES2/flextGLEmscripten.h index c357e5a57..58638b680 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGLEmscripten.h +++ b/src/MagnumExternal/OpenGL/GLES2/flextGLEmscripten.h @@ -506,17 +506,6 @@ typedef khronos_uint64_t GLuint64; #define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT 0x8E8E #define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT 0x8E8F -/* GL_EXT_texture_norm16 */ - -#define GL_R16_EXT 0x822A -#define GL_RG16_EXT 0x822C -#define GL_RGBA16_EXT 0x805B -#define GL_RGB16_EXT 0x8054 -#define GL_R16_SNORM_EXT 0x8F98 -#define GL_RG16_SNORM_EXT 0x8F99 -#define GL_RGB16_SNORM_EXT 0x8F9A -#define GL_RGBA16_SNORM_EXT 0x8F9B - /* GL_EXT_texture_compression_s3tc */ #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 From 5065e9d87ce37445b62b4e1b3e465dacb840589e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 20:42:05 +0100 Subject: [PATCH 020/161] Platform: suggest good practice when setting configuration flags. --- src/Magnum/Platform/EmscriptenApplication.h | 6 ++++-- src/Magnum/Platform/GlfwApplication.h | 9 ++++++--- src/Magnum/Platform/Sdl2Application.h | 9 ++++++--- src/Magnum/Platform/WindowlessEglApplication.h | 5 +++-- src/Magnum/Platform/WindowlessGlxApplication.h | 5 +++-- src/Magnum/Platform/WindowlessWglApplication.h | 5 +++-- src/Magnum/Platform/WindowlessWindowsEglApplication.h | 4 +++- 7 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index 3c7f2659c..ddc1fb2e2 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -1006,8 +1006,10 @@ class EmscriptenApplication::GLConfiguration { * @brief Set context flags * @return Reference to self (for method chaining) * - * Default is @ref Flag::EnableExtensionsByDefault. - * @see @ref addFlags(), @ref clearFlags(), @ref GL::Context::flags() + * Default is @ref Flag::EnableExtensionsByDefault. To avoid clearing + * default flags by accident, prefer to use @ref addFlags() and + * @ref clearFlags() instead. + * @see @ref GL::Context::flags() */ GLConfiguration& setFlags(Flags flags) { _flags = flags; diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 3706d7e5d..c45d403ce 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -834,8 +834,9 @@ class GlfwApplication::GLConfiguration { * @return Reference to self (for method chaining) * * Default is @ref Flag::ForwardCompatible on desktop GL and no flags - * on OpenGL ES. - * @see @ref addFlags(), @ref clearFlags(), @ref GL::Context::flags() + * on OpenGL ES. To avoid clearing default flags by accident, prefer to + * use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() */ GLConfiguration& setFlags(Flags flags) { _flags = flags; @@ -1250,7 +1251,9 @@ class GlfwApplication::Configuration { * @brief Set window flags * @return Reference to self (for method chaining) * - * Default is @ref WindowFlag::Focused. + * Default is @ref WindowFlag::Focused. To avoid clearing default flags + * by accident, prefer to use @ref addWindowFlags() and + * @ref clearWindowFlags() instead. */ Configuration& setWindowFlags(WindowFlags windowFlags) { _windowFlags = windowFlags; diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index ec37791f6..91fb46abb 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -1288,8 +1288,9 @@ class Sdl2Application::GLConfiguration { * @return Reference to self (for method chaining) * * Default is @ref Flag::ForwardCompatible on desktop GL and no flags - * on OpenGL ES. - * @see @ref addFlags(), @ref clearFlags(), @ref GL::Context::flags() + * on OpenGL ES. To avoid clearing default flags by accident, prefer to + * use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() * @requires_gles Context flags are not available in WebGL. */ GLConfiguration& setFlags(Flags flags) { @@ -1823,7 +1824,9 @@ class Sdl2Application::Configuration { * @brief Set window flags * @return Reference to self (for method chaining) * - * Default are none. + * Default are none. To avoid clearing default flags by accident, + * prefer to use @ref addWindowFlags() and @ref clearWindowFlags() + * instead. */ Configuration& setWindowFlags(WindowFlags flags) { _windowFlags = flags; diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index e9b9f06bb..ec17eb69a 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -231,8 +231,9 @@ class WindowlessEglContext::Configuration { * @return Reference to self (for method chaining) * * Default is @ref Flag::ForwardCompatible on desktop GL and no flags - * on OpenGL ES. - * @see @ref addFlags(), @ref clearFlags(), @ref GL::Context::flags() + * on OpenGL ES. To avoid clearing default flags by accident, prefer to + * use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() * @requires_gles Context flags are not available in WebGL. */ Configuration& setFlags(Flags flags) { diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 2647d7fac..9577f2197 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -228,8 +228,9 @@ class WindowlessGlxContext::Configuration { * @return Reference to self (for method chaining) * * Default is @ref Flag::ForwardCompatible on desktop GL and no flags - * on OpenGL ES. - * @see @ref addFlags(), @ref clearFlags(), @ref GL::Context::flags() + * on OpenGL ES. To avoid clearing default flags by accident, prefer to + * use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() */ Configuration& setFlags(Flags flags) { _flags = flags; diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 3ff1021b0..999880de2 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -215,8 +215,9 @@ class WindowlessWglContext::Configuration { * @return Reference to self (for method chaining) * * Default is @ref Flag::ForwardCompatible on desktop GL and no flags - * on OpenGL ES. - * @see @ref addFlags(), @ref clearFlags(), @ref GL::Context::flags() + * on OpenGL ES. To avoid clearing default flags by accident, prefer to + * use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() */ Configuration& setFlags(Flags flags) { _flags = flags; diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 06c209bb0..49c28621d 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -190,7 +190,9 @@ class WindowlessWindowsEglContext::Configuration { * @brief Set context flags * @return Reference to self (for method chaining) * - * Default is no flag. See also @ref GL::Context::flags(). + * Default is no flag. To avoid clearing default flags by accident, + * prefer to use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() */ Configuration& setFlags(Flags flags) { _flags = flags; From 67eed6d546d1b60c64992bcf18e8bc0ce5ad6ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 20:47:38 +0100 Subject: [PATCH 021/161] Platform: add missing EmscriptenApp::Config::{add,clear}WindowFlags(). All other apps have it. --- doc/changelog.dox | 3 ++ src/Magnum/Platform/EmscriptenApplication.h | 33 +++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/doc/changelog.dox b/doc/changelog.dox index 3a715882f..2319a2209 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -226,6 +226,9 @@ See also: other context classes - Undefining even more noise from `Xlib.h` (see [mosra/magnum#498](https://github.com/mosra/magnum/pull/498)) +- Added @ref Platform::EmscriptenApplication::Configuration::addWindowFlags() + and @ref Platform::EmscriptenApplication::Configuration::clearWindowFlags() + for consistency with other application implementations @subsubsection changelog-latest-changes-shaders Shaders library diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index ddc1fb2e2..1f16dfbb9 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -1232,12 +1232,45 @@ class EmscriptenApplication::Configuration { /** * @brief Set window flags * @return Reference to self (for method chaining) + * + * Default are none. To avoid clearing default flags by accident, + * prefer to use @ref addWindowFlags() and @ref clearWindowFlags() + * instead. */ Configuration& setWindowFlags(WindowFlags windowFlags) { _windowFlags = windowFlags; return *this; } + /** + * @brief Add window flags + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setWindowFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearWindowFlags() + */ + Configuration& addWindowFlags(WindowFlags flags) { + _windowFlags |= flags; + return *this; + } + + /** + * @brief Clear window flags + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setWindowFlags(), ANDs the inverse of @p flags with + * existing instead of replacing them. Useful for removing default + * flags. + * @see @ref addWindowFlags() + */ + Configuration& clearWindowFlags(WindowFlags flags) { + _windowFlags &= ~flags; + return *this; + } + private: Vector2i _size; Vector2 _dpiScaling; From fd1492f56b23abd1846b2b13c5825ad19aa3037b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 21:27:50 +0100 Subject: [PATCH 022/161] GL: introduce Context::Configuration mirroring --magnum-* arguments. Disabling engine startup log or modifying enabled extensions / workarounds from the application side was one of the common pain points and this should *finally* solve the problem. This Configuration is now inherited by the usual Platform::*Application::GLConfiguration / Platform::Windowless*Application::Configuration classes people are used to, so for the end user it's just as if these classes got a bunch new options. Having this, I also extended the ContextGLTest to verify that the Configuration and command-line options do what's expected because that hadn't automated tests until now. The test is mostly a copy of what I did for Vulkan already, nothing special. Additionally all Platform*ApplicationTest executables gained a new --quiet option to verify that the GL::Context::Configuration subset gets correctly passed from the Application code, because that's something we can't really verify in an automated way. --- doc/changelog.dox | 15 +- doc/getting-started.dox | 2 +- doc/opengl-workarounds.dox | 2 +- doc/troubleshooting.dox | 2 +- src/Magnum/Audio/Context.h | 6 +- src/Magnum/GL/Context.cpp | 75 ++++- src/Magnum/GL/Context.h | 291 ++++++++++++++++-- src/Magnum/GL/DebugOutput.h | 4 +- .../GL/Implementation/driverSpecific.cpp | 23 ++ src/Magnum/GL/OpenGLTester.h | 2 +- src/Magnum/GL/Test/ContextGLTest.cpp | 125 +++++++- src/Magnum/GL/Test/ContextTest.cpp | 227 +++++++++++++- src/Magnum/Platform/AbstractXApplication.cpp | 2 +- src/Magnum/Platform/AbstractXApplication.h | 21 +- src/Magnum/Platform/AndroidApplication.cpp | 2 +- src/Magnum/Platform/AndroidApplication.h | 21 +- src/Magnum/Platform/EmscriptenApplication.cpp | 7 +- src/Magnum/Platform/EmscriptenApplication.h | 44 ++- src/Magnum/Platform/GLContext.h | 42 ++- src/Magnum/Platform/GlfwApplication.cpp | 11 +- src/Magnum/Platform/GlfwApplication.h | 48 ++- src/Magnum/Platform/Sdl2Application.cpp | 26 +- src/Magnum/Platform/Sdl2Application.h | 79 +++-- .../Test/EmscriptenApplicationTest.cpp | 10 +- .../Platform/Test/GlfwApplicationTest.cpp | 12 +- .../Platform/Test/GlxApplicationTest.cpp | 6 +- .../Platform/Test/Sdl2ApplicationTest.cpp | 12 +- .../Test/WindowlessCglApplicationTest.cpp | 16 +- .../Test/WindowlessEglApplicationTest.cpp | 16 +- .../Test/WindowlessGlxApplicationTest.cpp | 16 +- .../Test/WindowlessIosApplicationTest.cpp | 16 +- .../Test/WindowlessWglApplicationTest.cpp | 16 +- .../WindowlessWindowsEglApplicationTest.cpp | 16 +- .../Platform/Test/XEglApplicationTest.cpp | 7 +- .../Platform/WindowlessCglApplication.cpp | 4 +- .../Platform/WindowlessCglApplication.h | 23 +- .../Platform/WindowlessEglApplication.cpp | 30 +- .../Platform/WindowlessEglApplication.h | 70 +++-- .../Platform/WindowlessGlxApplication.cpp | 28 +- .../Platform/WindowlessGlxApplication.h | 48 ++- .../Platform/WindowlessIosApplication.h | 22 +- .../Platform/WindowlessWglApplication.cpp | 22 +- .../Platform/WindowlessWglApplication.h | 48 ++- .../WindowlessWindowsEglApplication.cpp | 5 +- .../WindowlessWindowsEglApplication.h | 50 ++- src/Magnum/Platform/gl-info.cpp | 2 +- src/Magnum/Text/fontconverter.cpp | 2 +- .../TextureTools/distancefieldconverter.cpp | 2 +- 48 files changed, 1309 insertions(+), 267 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 2319a2209..ef79ad9d2 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -49,6 +49,12 @@ See also: @subsubsection changelog-latest-new-gl GL library +- New @ref GL::Context::Configuration class providing runtime alternatives to + the `--magnum-log`, `--magnum-gpu-validation`, `--magnum-disable-extensions` + and `--magnum-disable-workarounds` command line options. The class is then + inherited by all @ref Platform::Sdl2Application::GLConfiguration "Platform::*Application::GLConfiguration" + and @ref Platform::WindowlessEglApplication::Configuration "Platform::Windowless*Application::Configuration" + classes. - Implemented @gl_extension{EXT,texture_norm16} and @webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making normalized 16-bit texture and renderbuffer formats available on all @@ -1412,7 +1418,8 @@ Released 2019-10-24, tagged as (see the @cpp "swiftshader-broken-shader-vertex-id" @ce workaround in @ref opengl-workarounds for more information). This pseudo-extension can be also explicitly disabled using the usual `--magnum-disable-extensions` - @ref GL-Context-command-line "command-line option" for testing purposes. + @ref GL-Context-usage-command-line "command-line option" for testing + purposes. - An assorted collection of workarounds for Intel Windows drivers "fixing" various issues related to @gl_extension{ARB,direct_state_access} by using a non-DSA code path in the affected cases --- see @@ -1463,7 +1470,7 @@ Released 2019-10-24, tagged as a defined output. On core and ES/WebGL contexts this is enabled implicitly, but for example NVidia drivers have @cpp gl_PointCoord @ce undefined when `GL_POINT_SPRITE` is not enabled on compatibility contexts. -- New `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" +- New `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" and a corresponding environment variable to conveniently enable @gl_extension{KHR,debug} debug output. This flag also causes @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" @@ -1476,7 +1483,7 @@ Released 2019-10-24, tagged as @ref GL::Buffer::setData() / @ref GL::Buffer::setSubData() for a succint upload of basic types - Added an ability to use Magnum with multiple OpenGL contexts using - @ref GL::Context::makeCurrent(), see @ref GL-Context-multiple for more + @ref GL::Context::makeCurrent(), see @ref GL-Context-usage-multiple for more information - @ref GL::AbstractFramebuffer::read(), @ref GL::Texture::image(), @ref GL::Texture::subImage(), @ref GL::Texture::compressedImage(), @@ -1678,7 +1685,7 @@ Released 2019-10-24, tagged as - @ref GL::OpenGLTester no longer implicitly enables @ref GL::DebugOutput as it can be quite spammy when complex shaders or benchmarks are allowed. For easier debugging, users are encouraged to use the new - `--magnum-gpu-validation` @ref GL-Context-command-line "command line option" + `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command line option" instead. - Added an ability to create @ref GL::DynamicAttribute directly from a @ref GL::Attribute diff --git a/doc/getting-started.dox b/doc/getting-started.dox index 9e9f35dd5..544bc2eb5 100644 --- a/doc/getting-started.dox +++ b/doc/getting-started.dox @@ -282,7 +282,7 @@ Hello! This application is running on OpenGL 4.5 using GeForce GT 740M @image html getting-started-blue.png width=410px -The barebones application accepts various @ref GL-Context-command-line "command-line arguments", +The barebones application accepts various @ref GL-Context-usage-command-line "command-line arguments", pass `--magnum-help` to see them all. Depending on your platform, these can adjust HiDPI scaling, enable GPU command validation or for example switch to a different GPU device. diff --git a/doc/opengl-workarounds.dox b/doc/opengl-workarounds.dox index 7cdc9fec1..6ec935452 100644 --- a/doc/opengl-workarounds.dox +++ b/doc/opengl-workarounds.dox @@ -49,7 +49,7 @@ Using driver workarounds: These identifiers correspond to the strings in the listing below. For debugging and diagnostic purposes it's possible to disable particular workarounds by passing their identifier string to the `--magnum-disable-workarounds` -command-line option. See @ref GL-Context-command-line for more information. +command-line option. See @ref GL-Context-usage-command-line for more information. @m_class{m-console-wrap} diff --git a/doc/troubleshooting.dox b/doc/troubleshooting.dox index f70d9054d..909788932 100644 --- a/doc/troubleshooting.dox +++ b/doc/troubleshooting.dox @@ -54,7 +54,7 @@ or crashes on GL calls, you might want to try these things: - Enable @ref GL::DebugOutput "debug output" to see more detailed errors, warnings and performance hints. You can do that easily through the - `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" + `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" or an environment variable. - If you are on Mac, the native OpenGL implementation doesn't support this. Instead you can manually verify that diff --git a/src/Magnum/Audio/Context.h b/src/Magnum/Audio/Context.h index e9f7eeab3..25620bd79 100644 --- a/src/Magnum/Audio/Context.h +++ b/src/Magnum/Audio/Context.h @@ -110,9 +110,9 @@ options passed to the application itself. Options that don't have this prefix are completely ignored, see documentation of the @ref Utility-Arguments-delegating "Utility::Arguments" class for details. Moreover, `--magnum`-prefixed options unrelated to audio (such as those defined -by @ref GL-Context-command-line "GL::Context") are ignored as well. In order to -provide a complete help and command-line argument diagnostic, you should -instantiate this class *after* @ref GL::Context. +by @ref GL-Context-usage-command-line "GL::Context") are ignored as well. In +order to provide a complete help and command-line argument diagnostic, you +should instantiate this class *after* @ref GL::Context. */ class MAGNUM_AUDIO_EXPORT Context { public: diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index e47604bf6..2fe912ccc 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -749,15 +749,40 @@ Context::~Context() { if(currentContext == this) currentContext = nullptr; } -void Context::create() { +void Context::create(const Configuration& configuration) { /* Hard exit if the context cannot be created */ - if(!tryCreate()) std::exit(1); + if(!tryCreate(configuration)) std::exit(1); } -bool Context::tryCreate() { +bool Context::tryCreate(const Configuration& configuration) { CORRADE_ASSERT(_version == Version::None, "Platform::Context::tryCreate(): context already created", false); + /* Merge the configuration with parameters passed on the command line / + environment. For the log command-line gets a priority -- if it says + quiet, it'll override the verbose setting from the configuration; if + it says verbose, the quiet setting from the configuration will be + ignored */ + if((configuration.flags() & Configuration::Flag::VerboseLog) && (_internalFlags & InternalFlag::DisplayInitializationLog)) + _internalFlags |= InternalFlag::DisplayVerboseInitializationLog; + else if((configuration.flags() & Configuration::Flag::QuietLog) && !(_internalFlags >= InternalFlag::DisplayVerboseInitializationLog)) + _internalFlags &= ~InternalFlag::DisplayInitializationLog; + + /* GPU validation is enabled if either enables it */ + if(configuration.flags() & Configuration::Flag::GpuValidation) + _internalFlags |= InternalFlag::GpuValidation; + + /* Driver workarounds get merged. Not using disableDriverWorkaround() here + since the Configuration already contains the internal string views. */ + for(const Containers::StringView workaround: configuration.disabledWorkarounds()) + arrayAppend(_driverWorkarounds, Containers::InPlaceInit, workaround, true); + + /* Extensions get merged also. Here we had the chance to force users to + give us the predefined extension types so no need to search for their + IDs */ + for(const Extension& extension: configuration.disabledExtensions()) + arrayAppend(_disabledExtensions, extension); + /* Load GL function pointers. Pass this instance to it so it can use it for potential driver-specific workarounds. */ if(_functionLoader) _functionLoader(*this); @@ -1139,6 +1164,50 @@ void Context::resetState(const States states) { #endif } +Context::Configuration::Configuration() = default; + +Context::Configuration::Configuration(const Configuration& other): _flags{other._flags} { + addDisabledWorkarounds(other._disabledWorkarounds); + addDisabledExtensions(other._disabledExtensions); +} + +Context::Configuration::Configuration(Configuration&&) noexcept = default; + +Context::Configuration::~Configuration() = default; + +Context::Configuration& Context::Configuration::operator=(const Configuration& other) { + _flags = other._flags; + arrayResize(_disabledWorkarounds, 0); + /** @todo arrayClear(), ffs */ + arrayResize(_disabledExtensions, Containers::NoInit, 0); + addDisabledWorkarounds(other._disabledWorkarounds); + addDisabledExtensions(other._disabledExtensions); + return *this; +} + +Context::Configuration& Context::Configuration::operator=(Configuration&&) noexcept = default; + +Containers::ArrayView Context::Configuration::disabledWorkarounds() const { + return _disabledWorkarounds; +} + +Containers::ArrayView Context::Configuration::disabledExtensions() const { + return _disabledExtensions; +} + +Context::Configuration& Context::Configuration::addDisabledWorkarounds(std::initializer_list workarounds) { + return addDisabledWorkarounds(Containers::arrayView(workarounds)); +} + +Context::Configuration& Context::Configuration::addDisabledExtensions(Containers::ArrayView extensions) { + arrayAppend(_disabledExtensions, extensions); + return *this; +} + +Context::Configuration& Context::Configuration::addDisabledExtensions(std::initializer_list extensions) { + return addDisabledExtensions(Containers::arrayView(extensions)); +} + #ifndef DOXYGEN_GENERATING_OUTPUT #ifndef MAGNUM_TARGET_WEBGL Debug& operator<<(Debug& debug, const Context::Flag value) { diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index c776bee92..c26e72455 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -108,18 +108,32 @@ class MAGNUM_GL_EXPORT Extension { @brief Magnum OpenGL context Provides access to OpenGL version and extension information and manages -Magnum's internal OpenGL state tracker. An instance available through -@ref Context::current() is automatically created during construction of -`Platform::*Application` classes and you can safely assume the instance is -available during the whole `*Application` lifetime. It's also possible to -create the context without using any `*Application` class using the +Magnum's internal OpenGL state tracker. + +@section GL-Context-usage Creating a context + +In order to use any Magnum OpenGL functionality, an instance of this class has +to exist and be made current. If you use any `Platform::*Application` classes, +an instance available through @ref Context::current() is automatically created +during construction (or after @ref Platform::Sdl2Application::create() "Platform::*Application::create()" +/ @relativeref{Platform::Sdl2Application,tryCreate()} and you can safely assume +the instance is available during the whole `*Application` lifetime. It's also +possible to create the context without using any `*Application` class using the @ref Platform::GLContext subclass, see @ref platform for more information. -@section GL-Context-command-line Command-line options +Various options can be passed using the @ref Configuration class, which is then +extended by various +@ref Platform::Sdl2Application::GLConfiguration "Platform::*Application::GLConfiguration" +and @ref Platform::WindowlessEglContext::Configuration "Platform::Windowless*Application::Configuration" +subclasses. + +@subsection GL-Context-usage-command-line Command-line options -The context is configurable through command-line options, that are passed -either from the `Platform::*Application` classes or from the -@ref Platform::GLContext class. Usage: +In addition to the @ref Configuration, the context is configurable through +command-line options, that are passed either from the `Platform::*Application` +classes or from the @ref Platform::GLContext class. In case an option is set in +both the @ref Configuration and on command-line / environment, the two are +combined together --- flags ORed together, lists joined. Usage: @code{.sh} [--magnum-help] [--magnum-disable-workarounds LIST] @@ -134,20 +148,23 @@ Arguments: - `--magnum-help` --- display this help message and exit - `--magnum-disable-workarounds LIST` --- driver workarounds to disable (see @ref opengl-workarounds for detailed info) (environment: - `MAGNUM_DISABLE_WORKAROUNDS`) + `MAGNUM_DISABLE_WORKAROUNDS`). Corresponds to + @ref Configuration::addDisabledWorkarounds(). - `--magnum-disable-extensions LIST` --- API extensions to disable - (environment: `MAGNUM_DISABLE_EXTENSIONS`) + (environment: `MAGNUM_DISABLE_EXTENSIONS`). Corresponds to + @ref Configuration::addDisabledExtensions(). - `--magnum-gpu-validation off|on` --- GPU validation using @gl_extension{KHR,debug}, if present (environment: `MAGNUM_GPU_VALIDATION`) (default: `off`). This sets up @ref DebugOutput callbacks and also causes @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" to be enabled for context creation for both windowed and windowless - applications on supported platforms + applications on supported platforms. Corresponds to + @ref Configuration::Flag::GpuValidation. - `--magnum-log default|quiet|verbose` --- console logging - (environment: `MAGNUM_LOG`) (default: `default`). If you need to suppress - the engine startup log from code, the recommended way is to redirect - @ref Utility-Debug-scoped-output "debug output to null" during context creation. + (environment: `MAGNUM_LOG`) (default: `default`). Corresponds to + @ref Configuration::Flag::QuietLog and + @relativeref{Configuration::Flag,VerboseLog}. Note that all options are prefixed with `--magnum-` to avoid conflicts with options passed to the application itself. Options that don't have this prefix @@ -158,15 +175,7 @@ Particular application implementations add more options for DPI scaling or GPU selection, see @ref Platform::Sdl2Application, @ref Platform::GlfwApplication and @ref Platform::WindowlessEglApplication for details. -@section GL-Context-multithreading Thread safety - -If Corrade is compiled with @ref CORRADE_BUILD_MULTITHREADED (the default), the -@ref hasCurrent() and @ref current() accessors are thread-local, matching the -OpenGL context thread locality. This might cause some performance penalties --- -if you are sure that you never need to have multiple independent thread-local -Magnum context, build Corrade with the option disabled. - -@section GL-Context-multiple Using multiple OpenGL contexts +@subsection GL-Context-usage-multiple Using multiple OpenGL contexts By default, Magnum assumes you have one OpenGL context active at all times, and all state tracking is done by the @ref Context instance that's associated with @@ -187,9 +196,19 @@ Once all needed instances are created, switch between them right after making the underlying GL context current: @snippet MagnumGL-framebuffer.cpp Context-makeCurrent + +@section GL-Context-multithreading Thread safety + +If Corrade is compiled with @ref CORRADE_BUILD_MULTITHREADED (the default), the +@ref hasCurrent() and @ref current() accessors are thread-local, matching the +OpenGL context thread locality. This might cause some performance penalties --- +if you are sure that you never need to have multiple independent thread-local +Magnum context, build Corrade with the option disabled. */ class MAGNUM_GL_EXPORT Context { public: + class Configuration; + #ifndef MAGNUM_TARGET_WEBGL /** * @brief Context flag @@ -204,7 +223,8 @@ class MAGNUM_GL_EXPORT Context { * Debug context. Enabled automatically by @ref Platform windowed * and windowless application implementations if the * `--magnum-gpu-validation` - * @ref GL-Context-command-line "command-line option" is present. + * @ref GL-Context-usage-command-line "command-line option" is + * present. * @requires_gl43 Extension @gl_extension{KHR,debug} * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / * @gl_extension{KHR,debug} @@ -485,7 +505,7 @@ class MAGNUM_GL_EXPORT Context { * @m_since{2019,10} * * To be used when you need to manage multiple OpenGL contexts. See - * @ref GL-Context-multiple for more information. + * @ref GL-Context-usage-multiple for more information. */ static void makeCurrent(Context* context); @@ -693,8 +713,10 @@ class MAGNUM_GL_EXPORT Context { * @brief Whether given extension is disabled * * Can be used for detecting driver bug workarounds. Disabled - * extensions return `false` in @ref isExtensionSupported() even if - * they are advertised as being supported by the driver. + * extensions return @cpp false @ce in @ref isExtensionSupported() even + * if they are advertised as being supported by the driver. + * @see @ref Configuration::addDisabledExtensions(), + * @ref GL-Context-usage-command-line */ template bool isExtensionDisabled() const { return isExtensionDisabled(version()); @@ -705,6 +727,8 @@ class MAGNUM_GL_EXPORT Context { * * Similar to above, but can also check for extensions which are * disabled only for particular versions. + * @see @ref Configuration::addDisabledExtensions(), + * @ref GL-Context-usage-command-line */ template bool isExtensionDisabled(Version version) const { static_assert(Implementation::IsExtension::value, "expected an OpenGL extension"); @@ -717,8 +741,11 @@ class MAGNUM_GL_EXPORT Context { * @brief Whether given extension is disabled * * Can be used e.g. for listing extensions available on current - * hardware, but for general usage prefer @ref isExtensionDisabled() const, - * as it does most operations in compile time. + * hardware, but for general usage prefer + * @ref isExtensionDisabled() const, as it does most operations at + * compile time. + * @see @ref Configuration::addDisabledExtensions(), + * @ref GL-Context-usage-command-line */ bool isExtensionDisabled(const Extension& extension) const { return isVersionSupported(extension.requiredVersion()) && !isVersionSupported(_extensionRequiredVersion[extension.index()]); @@ -786,8 +813,8 @@ class MAGNUM_GL_EXPORT Context { explicit Context(NoCreateT, Utility::Arguments&& args, Int argc, const char** argv, void functionLoader(Context&)): Context{NoCreate, args, argc, argv, functionLoader} {} explicit Context(NoCreateT, Utility::Arguments& args, Int argc, const char** argv, void functionLoader(Context&)); - bool tryCreate(); - void create(); + bool tryCreate(const Configuration& configuration); + void create(const Configuration& configuration); private: #ifndef DOXYGEN_GENERATING_OUTPUT /* https://bugzilla.gnome.org/show_bug.cgi?id=776986 */ @@ -847,6 +874,206 @@ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDriver value); /** @debugoperatorclassenum{Context,Context::DetectedDrivers} */ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Context::DetectedDrivers value); +/** +@brief Configuration +@m_since_latest + +Affects how Magnum's context creation behaves. See @ref GL-Context-usage for +more information. +@see @ref Platform::GLContext::GLContext(), + @ref Platform::GLContext::create(), + @ref Platform::GLContext::tryCreate() +*/ +class MAGNUM_GL_EXPORT Context::Configuration { + public: + /** + * @brief Context setup flag + * + * Flags affecting the actual GL context are merged with this enum in + * @ref Platform::Sdl2Application::GLConfiguration::Flag "Platform::*Application::GLConfiguration::Flag" + * and @ref Platform::WindowlessEglContext::Configuration::Flag "Platform::Windowless*Application::Configuration::Flag" + * and after context creation available through @ref Context::Flag / + * @ref Context::flags(). + * @see @ref Flags, @ref setFlags() + */ + enum class Flag: UnsignedLong { + /* Keeping the 32-bit range reserved for actual GL context flags */ + + /** + * Print only warnings and errors instead of the usual startup log + * listing used extensions and workarounds. Ignored if + * @ref Flag::VerboseLog is set. + * + * Corresponds to the `--magnum-log quiet` + * @ref GL-Context-usage-command-line "command-line option". + */ + QuietLog = 1ull << 61, + + /** + * Print additional information on startup in addition to the usual + * startup log that lists used extensions and workarounds. Has a + * precedence over @ref Flag::QuietLog. + * + * Corresponds to the `--magnum-log verbose` + * @ref GL-Context-usage-command-line "command-line option". + */ + VerboseLog = 1ull << 62, + + /** + * Enable GPU validation, if available. + * + * Corresponds to the `--magnum-gou-validation on` + * @ref GL-Context-usage-command-line "command-line option". + */ + GpuValidation = 1ull << 63 + }; + + /** + * @brief Context setup flags + * + * @see @ref setFlags(), @ref GL::Context::Flags + */ + typedef Containers::EnumSet Flags; + + /*implicit*/ Configuration(); + + /** @brief Copy constructor */ + /* The class has to be copyable in order to make command-line and + configuration options easy to merge in application implementations + -- these make a mutable copy and add what arrived via command line */ + Configuration(const Configuration& other); + + /** @brief Move constructor */ + Configuration(Configuration&&) noexcept; + + ~Configuration(); + + /** @brief Copy constructor */ + Configuration& operator=(const Configuration& other); + + /** @brief Move assignment */ + Configuration& operator=(Configuration&&) noexcept; + + /** @brief Context setup flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set context setup flags + * @return Reference to self (for method chaining) + * + * By default no flags are set. Note that subclasses might have + * different flag defaults, see their documentation for more + * information. To avoid clearing default flags by accident, prefer to + * use @ref addFlags() and @ref clearFlags() instead. + * + * Particular @ref Flag values correspond to the `--magnum-log` and + * `--magnum-gpu-validation` + * @ref GL-Context-usage-command-line "command-line options". + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + /** + * @brief Add context setup flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearFlags() + */ + Configuration& addFlags(Flags flags) { + _flags |= flags; + return *this; + } + + /** + * @brief Clear context setup flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing + * instead of replacing them. Useful for removing default flags. + * @see @ref addFlags() + */ + Configuration& clearFlags(Flags flags) { + _flags &= ~flags; + return *this; + } + + /** @brief Disabled driver workarounds */ + Containers::ArrayView disabledWorkarounds() const; + + /** + * @brief Add disabled driver workarounds + * @return Reference to self (for method chaining) + * + * Accepts strings from the list at @ref opengl-workarounds. Unknown + * workarounds are ignored with a warning. By default no workarounds + * are disabled. + * + * Corresponds to the `--magnum-disable-workarounds` + * @ref GL-Context-usage-command-line "command-line option". + */ + Configuration& addDisabledWorkarounds(Containers::ArrayView workarounds); + /** @overload */ + Configuration& addDisabledWorkarounds(std::initializer_list workarounds); + + /** @brief Disabled extensions */ + Containers::ArrayView disabledExtensions() const; + + /** + * @brief Add disabled extensions + * @return Reference to self (for method chaining) + * + * By default no extensions are disabled, except for those disabled by + * driver workarounds. + * + * Corresponds to the `--magnum-disable-extensions` + * @ref GL-Context-usage-command-line "command-line option". + */ + Configuration& addDisabledExtensions(Containers::ArrayView extensions); + /** @overload */ + Configuration& addDisabledExtensions(std::initializer_list extensions); + /** @overload */ + template Configuration& addDisabledExtensions() { + static_assert(Implementation::IsExtension::value, "expected only OpenGL extensions"); + return addDisabledExtensions({E{}...}); + } + + private: + Flags _flags; + Containers::Array _disabledWorkarounds; + Containers::Array _disabledExtensions; +}; + +#ifndef DOXYGEN_GENERATING_OUTPUT +#define MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Type) \ + Type& addDisabledWorkarounds(Containers::ArrayView workarounds) { \ + GL::Context::Configuration::addDisabledWorkarounds(workarounds); \ + return *this; \ + } \ + Type& addDisabledWorkarounds(std::initializer_list workarounds) { \ + GL::Context::Configuration::addDisabledWorkarounds(workarounds); \ + return *this; \ + } \ + \ + Type& addDisabledExtensions(Containers::ArrayView extensions) { \ + GL::Context::Configuration::addDisabledExtensions(extensions); \ + return *this; \ + } \ + Type& addDisabledExtensions(std::initializer_list extensions) { \ + GL::Context::Configuration::addDisabledExtensions(extensions); \ + return *this; \ + } \ + template Type& addDisabledExtensions() { \ + GL::Context::Configuration::addDisabledExtensions(); \ + return *this; \ + } +#endif + +CORRADE_ENUMSET_OPERATORS(Context::Configuration::Flags) + /** @hideinitializer @brief Assert that given OpenGL version is supported @param version Version diff --git a/src/Magnum/GL/DebugOutput.h b/src/Magnum/GL/DebugOutput.h index 3982068c2..3bbe6a913 100644 --- a/src/Magnum/GL/DebugOutput.h +++ b/src/Magnum/GL/DebugOutput.h @@ -79,8 +79,8 @@ application itself by setting up message callback using @ref setCallback() or @par Enabling debug output from the command line / environment Apart from setting up the debug output callbacks manually, it's also possible to enable it conveniently using the `--magnum-gpu-validation` - @ref GL-Context-command-line "command-line or environment option" --- ideal - for quick debugging of rendering issues. If you are using application + @ref GL-Context-usage-command-line "command-line or environment option" --- + ideal for quick debugging of rendering issues. If you are using application classes from the @ref Platform namespace, this option also ensures that @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" is passed for context creation, both with windowed and windowless diff --git a/src/Magnum/GL/Implementation/driverSpecific.cpp b/src/Magnum/GL/Implementation/driverSpecific.cpp index 9b681b544..9ac84a136 100644 --- a/src/Magnum/GL/Implementation/driverSpecific.cpp +++ b/src/Magnum/GL/Implementation/driverSpecific.cpp @@ -616,4 +616,27 @@ void Context::setupDriverWorkarounds() { #endif } +Context::Configuration& Context::Configuration::addDisabledWorkarounds(Containers::ArrayView workarounds) { + arrayReserve(_disabledWorkarounds, _disabledWorkarounds.size() + workarounds.size()); + + for(const Containers::StringView workaround: workarounds) { + /* Find the workaround. Note that we'll add the found view to the array + and not the passed view, as the found view is guaranteed to stay in + scope */ + const Containers::StringView found = findWorkaround(workaround); + + /* Ignore unknown workarounds */ + /** @todo this will probably cause false positives when both GL and + Vulkan is used together? */ + if(found.isEmpty()) { + Warning{} << "GL::Context::Configuration::addDisabledWorkarounds(): unknown workaround" << workaround; + continue; + } + + arrayAppend(_disabledWorkarounds, Containers::InPlaceInit, found); + } + + return *this; +} + }} diff --git a/src/Magnum/GL/OpenGLTester.h b/src/Magnum/GL/OpenGLTester.h index d9da1a633..cf13f9aa0 100644 --- a/src/Magnum/GL/OpenGLTester.h +++ b/src/Magnum/GL/OpenGLTester.h @@ -132,7 +132,7 @@ by default to make the test output more readable. Instead of relying on debug output to report errors, the @ref MAGNUM_VERIFY_NO_GL_ERROR() macro should be used to reliably check for errors regardless of platform support. For easier debugging of OpenGL errors users are encuraged to use the -`--magnum-gpu-validation` @ref GL-Context-command-line "command line option", +`--magnum-gpu-validation` @ref GL-Context-usage-command-line "command line option", which is supported here as well as in all other application implementations. @section GL-OpenGLTester-benchmarks GPU time benchmarks diff --git a/src/Magnum/GL/Test/ContextGLTest.cpp b/src/Magnum/GL/Test/ContextGLTest.cpp index c51635338..d14910ca6 100644 --- a/src/Magnum/GL/Test/ContextGLTest.cpp +++ b/src/Magnum/GL/Test/ContextGLTest.cpp @@ -24,6 +24,9 @@ */ #include +#include +#include +#include #include #include @@ -43,6 +46,8 @@ struct ContextGLTest: OpenGLTester { void stringFlags(); + void constructConfiguration(); + void makeCurrent(); #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -58,10 +63,89 @@ struct ContextGLTest: OpenGLTester { void isExtensionDisabled(); }; +using namespace Containers::Literals; + +struct { + const char* name; + Containers::Optional needsExtensionPresent, needsExtensionMissing; + Context::Configuration::Flags flags; + Containers::Array disabledWorkarounds; + Containers::Array disabledExtensions; + Containers::Array args; + Containers::StringView logShouldContain, logShouldNotContain; +} ConstructConfigurationData[] { + {"default log", {}, {}, + {}, + {}, {}, {}, + "Renderer: ", {}}, + {"quiet", {}, {}, + Context::Configuration::Flag::QuietLog, + {}, {}, {}, + {}, "Renderer: "}, + {"quiet on command line", {}, {}, {}, {}, {}, + Containers::array({"", "--magnum-log", "quiet"}), + {}, "Renderer: "}, + {"quiet and verbose", {}, {}, + Context::Configuration::Flag::QuietLog|Context::Configuration::Flag::VerboseLog, + {}, {}, {}, + /* Verbose has a precedence */ + "Renderer: ", {}}, + {"quiet and verbose on command line", {}, {}, + Context::Configuration::Flag::QuietLog, + {}, {}, + Containers::array({"", "--magnum-log", "verbose"}), + /* Command-line has a precedence */ + "Renderer: ", {}}, + {"verbose and quiet on command line", {}, {}, + Context::Configuration::Flag::VerboseLog, + {}, {}, + Containers::array({"", "--magnum-log", "quiet"}), + /* Command-line has a precedence */ + {}, "Renderer: "}, + #ifndef MAGNUM_TARGET_GLES + {"default workarounds", {}, {}, {}, {}, {}, {}, + "\nUsing driver workarounds:\n no-layout-qualifiers-on-old-glsl\n", {}}, + {"disabled workaround", {}, {}, {}, + Containers::array({"no-layout-qualifiers-on-old-glsl"_s}), {}, {}, + {}, "no-layout-qualifiers-on-old-glsl"}, + {"disabled workaround on command line", {}, {}, {}, {}, {}, + Containers::array({"", "--magnum-disable-workarounds", "no-layout-qualifiers-on-old-glsl"}), + {}, "no-layout-qualifiers-on-old-glsl"}, + #endif + #ifndef MAGNUM_TARGET_GLES + {"default extensions ARB", + Extension{Extensions::ARB::texture_filter_anisotropic{}}, + {}, {}, {}, {}, {}, + " GL_ARB_texture_filter_anisotropic\n", {}}, + #endif + {"default extensions EXT", + Extension{Extensions::EXT::texture_filter_anisotropic{}}, + #ifndef MAGNUM_TARGET_GLES + Extension{Extensions::ARB::texture_filter_anisotropic{}}, + #else + {}, + #endif + {}, {}, {}, {}, + " GL_EXT_texture_filter_anisotropic\n", {}}, + {"disabled extension", + Extension{Extensions::EXT::texture_filter_anisotropic{}}, + {}, {}, {}, + Containers::array({Extensions::EXT::texture_filter_anisotropic{}}), {}, + "Disabling extensions:\n GL_EXT_texture_filter_anisotropic\n", {}}, + {"disabled extension on command line", + Extension{Extensions::EXT::texture_filter_anisotropic{}}, + {}, {}, {}, {}, + Containers::array({"", "--magnum-disable-extensions", "GL_EXT_texture_filter_anisotropic"}), + "Disabling extensions:\n GL_EXT_texture_filter_anisotropic\n", {}}, +}; + ContextGLTest::ContextGLTest() { - addTests({ - &ContextGLTest::stringFlags, + addTests({&ContextGLTest::stringFlags}); + + addInstancedTests({&ContextGLTest::constructConfiguration}, + Containers::arraySize(ConstructConfigurationData)); + addTests({ &ContextGLTest::makeCurrent, #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -116,6 +200,43 @@ void ContextGLTest::stringFlags() { } } +void ContextGLTest::constructConfiguration() { + auto&& data = ConstructConfigurationData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + if(std::getenv("MAGNUM_DISABLE_WORKAROUNDS")) + CORRADE_SKIP("Can't test with the MAGNUM_DISABLE_WORKAROUNDS environment variable set"); + if(std::getenv("MAGNUM_DISABLE_EXTENSIONS")) + CORRADE_SKIP("Can't test with the MAGNUM_DISABLE_EXTENSIONS environment variable set"); + + CORRADE_VERIFY(Context::hasCurrent()); + + if(data.needsExtensionPresent && !Context::current().isExtensionSupported(*data.needsExtensionPresent)) + CORRADE_SKIP(data.needsExtensionPresent->string() + std::string{" is not supported, skippping"}); + if(data.needsExtensionMissing && Context::current().isExtensionSupported(*data.needsExtensionMissing)) + CORRADE_SKIP(data.needsExtensionMissing->string() + std::string{" is supported, skippping"}); + + std::ostringstream out; + { + Context* current = &Context::current(); + Context::makeCurrent(nullptr); + Containers::ScopeGuard resetCurrent{current, Context::makeCurrent}; + + Debug redirectOut{&out}; + Platform::GLContext ctx{Int(data.args.size()), data.args, Context::Configuration{} + .setFlags(data.flags) + .addDisabledWorkarounds(data.disabledWorkarounds) + .addDisabledExtensions(data.disabledExtensions) + }; + } + + /** @todo TestSuite::Compare::StringContains / NotContains for proper diag */ + if(!data.logShouldContain.isEmpty()) + CORRADE_VERIFY(Containers::StringView{out.str()}.contains(data.logShouldContain)); + if(!data.logShouldNotContain.isEmpty()) + CORRADE_VERIFY(!Containers::StringView{out.str()}.contains(data.logShouldNotContain)); +} + void ContextGLTest::makeCurrent() { CORRADE_VERIFY(Context::hasCurrent()); diff --git a/src/Magnum/GL/Test/ContextTest.cpp b/src/Magnum/GL/Test/ContextTest.cpp index c393e1048..0651a2a31 100644 --- a/src/Magnum/GL/Test/ContextTest.cpp +++ b/src/Magnum/GL/Test/ContextTest.cpp @@ -25,7 +25,9 @@ #include #include +#include #include +#include #include #include "Magnum/GL/Context.h" @@ -39,6 +41,11 @@ struct ContextTest: TestSuite::Tester { void isExtension(); + void configurationConstruct(); + void configurationConstructUnknownWorkaround(); + void configurationConstructCopy(); + void configurationConstructMove(); + void constructNoCreate(); void constructCopyMove(); @@ -56,6 +63,11 @@ struct ContextTest: TestSuite::Tester { ContextTest::ContextTest() { addTests({&ContextTest::isExtension, + &ContextTest::configurationConstruct, + &ContextTest::configurationConstructUnknownWorkaround, + &ContextTest::configurationConstructCopy, + &ContextTest::configurationConstructMove, + &ContextTest::constructNoCreate, &ContextTest::constructCopyMove, @@ -71,7 +83,7 @@ ContextTest::ContextTest() { } void ContextTest::isExtension() { - CORRADE_VERIFY(Implementation::IsExtension::value); + CORRADE_VERIFY(Implementation::IsExtension::value); CORRADE_VERIFY(!Implementation::IsExtension::value); CORRADE_VERIFY(!Implementation::IsExtension::value); @@ -86,8 +98,9 @@ void ContextTest::isExtension() { CORRADE_VERIFY(!Implementation::IsExtension::value); } - /* Variadic check (used in variadic addEnabledExtensions()), check that it - properly fails for each occurence of a non-extension */ + /* Variadic check (used in variadic Configuration::addDisabledExtensions()), + check that it properly fails for each occurence of a non-extension */ + #ifndef MAGNUM_TARGET_WEBGL CORRADE_VERIFY((Implementation::IsExtension< Extensions::KHR::debug, Extensions::EXT::texture_filter_anisotropic, @@ -104,11 +117,219 @@ void ContextTest::isExtension() { Extensions::KHR::debug, Extensions::EXT::texture_filter_anisotropic, Extension>::value)); + #else + CORRADE_VERIFY((Implementation::IsExtension< + Extensions::OES::texture_float_linear, + Extensions::EXT::texture_filter_anisotropic, + Extensions::WEBGL::compressed_texture_s3tc>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extension, + Extensions::OES::texture_float_linear, + Extensions::EXT::texture_filter_anisotropic>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::OES::texture_float_linear, + Extension, + Extensions::EXT::texture_filter_anisotropic>::value)); + CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::OES::texture_float_linear, + Extensions::EXT::texture_filter_anisotropic, + Extension>::value)); + #endif /* Empty variadic list should return true */ CORRADE_VERIFY(Implementation::IsExtension<>::value); } +void ContextTest::configurationConstruct() { + #ifndef MAGNUM_TARGET_GLES + const Containers::StringView a = "no-layout-qualifiers-on-old-glsl"; + const Containers::StringView b = "nv-compressed-block-size-in-bits"; + const Containers::StringView c = "nv-cubemap-inconsistent-compressed-image-size"; + #elif !defined(MAGNUM_TARGET_WEBGL) + const Containers::StringView a = "swiftshader-no-empty-egl-context-flags"; + const Containers::StringView b = "swiftshader-egl-context-needs-pbuffer"; + const Containers::StringView c = "angle-chatty-shader-compiler"; + #else + /* No general WebGL workarounds to test */ + #endif + /* Deliberately not having the literals global to test that they get + converted to something else */ + CORRADE_VERIFY(!(a.flags() & Containers::StringViewFlag::Global)); + + Context::Configuration configuration; + configuration + .setFlags(Context::Configuration::Flag::GpuValidation| + Context::Configuration::Flag::VerboseLog) + #ifndef MAGNUM_TARGET_WEBGL + .addDisabledWorkarounds({a, b}) + .addDisabledWorkarounds({c}) + #endif + #ifndef MAGNUM_TARGET_WEBGL + .addDisabledExtensions({Extensions::EXT::texture_filter_anisotropic{}, + Extensions::KHR::debug{}}) + .addDisabledExtensions() + #else + .addDisabledExtensions({Extensions::EXT::texture_filter_anisotropic{}, + Extensions::EXT::texture_compression_rgtc{}}) + .addDisabledExtensions() + #endif + ; + + CORRADE_COMPARE(UnsignedLong(configuration.flags()), UnsignedLong( + Context::Configuration::Flag::GpuValidation| + Context::Configuration::Flag::VerboseLog)); + + /* The workaround strings should get interned */ + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE_AS(configuration.disabledWorkarounds(), + Containers::arrayView({a, b, c}), + TestSuite::Compare::Container); + CORRADE_VERIFY(configuration.disabledWorkarounds()[0].data() != a.data()); + CORRADE_VERIFY(configuration.disabledWorkarounds()[1].data() != b.data()); + CORRADE_VERIFY(configuration.disabledWorkarounds()[2].data() != c.data()); + CORRADE_COMPARE(configuration.disabledWorkarounds()[0].flags(), + Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + CORRADE_COMPARE(configuration.disabledWorkarounds()[1].flags(), + Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + CORRADE_COMPARE(configuration.disabledWorkarounds()[2].flags(), + Containers::StringViewFlag::Global|Containers::StringViewFlag::NullTerminated); + #endif + + CORRADE_COMPARE(configuration.disabledExtensions().size(), 4); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE(configuration.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index); + CORRADE_COMPARE(configuration.disabledExtensions()[1].index(), Extensions::KHR::debug::Index); + CORRADE_COMPARE(configuration.disabledExtensions()[2].index(), Extensions::KHR::robustness::Index); + CORRADE_COMPARE(configuration.disabledExtensions()[3].index(), Extensions::KHR::texture_compression_astc_hdr::Index); + #else + CORRADE_COMPARE(configuration.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index); + CORRADE_COMPARE(configuration.disabledExtensions()[1].index(), Extensions::EXT::texture_compression_rgtc::Index); + CORRADE_COMPARE(configuration.disabledExtensions()[2].index(), Extensions::EXT::float_blend::Index); + CORRADE_COMPARE(configuration.disabledExtensions()[3].index(), Extensions::OES::texture_float_linear::Index); + #endif +} + +void ContextTest::configurationConstructUnknownWorkaround() { + Context::Configuration configuration; + + /* Unknown workarounds should get ignored -- we're storing views on + internally known workaround strings to avoid allocations so there's no + other way */ + std::ostringstream out; + Warning redirectWarning{&out}; + configuration.addDisabledWorkarounds({"all-drivers-are-shit"}); + CORRADE_VERIFY(configuration.disabledWorkarounds().empty()); + CORRADE_COMPARE(out.str(), "GL::Context::Configuration::addDisabledWorkarounds(): unknown workaround all-drivers-are-shit\n"); +} + +void ContextTest::configurationConstructCopy() { + #ifndef MAGNUM_TARGET_GLES + Containers::StringView workaround = "no-layout-qualifiers-on-old-glsl"; + Containers::StringView another = "nv-compressed-block-size-in-bits"; + #elif !defined(MAGNUM_TARGET_WEBGL) + Containers::StringView workaround = "swiftshader-no-empty-egl-context-flags"; + Containers::StringView another = "angle-chatty-shader-compiler"; + #else + /* No general WebGL workarounds to test */ + #endif + + Context::Configuration a; + a.setFlags(Context::Configuration::Flag::VerboseLog) + #ifndef MAGNUM_TARGET_WEBGL + .addDisabledWorkarounds({workaround}) + #endif + .addDisabledExtensions(); + + Context::Configuration b = a; + CORRADE_COMPARE(UnsignedLong(b.flags()), UnsignedLong(Context::Configuration::Flag::VerboseLog)); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE_AS(b.disabledWorkarounds(), + Containers::arrayView({workaround}), + TestSuite::Compare::Container); + #endif + CORRADE_COMPARE(b.disabledExtensions().size(), 1); + CORRADE_COMPARE(b.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index); + + Context::Configuration c; + c.setFlags(Context::Configuration::Flag::QuietLog) + #ifndef MAGNUM_TARGET_WEBGL + .addDisabledWorkarounds({another}) + .addDisabledExtensions() + #else + .addDisabledExtensions() + #endif + ; + + c = b; + CORRADE_COMPARE(UnsignedLong(c.flags()), UnsignedLong(Context::Configuration::Flag::VerboseLog)); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE_AS(c.disabledWorkarounds(), + Containers::arrayView({workaround}), + TestSuite::Compare::Container); + #endif + CORRADE_COMPARE(c.disabledExtensions().size(), 1); + CORRADE_COMPARE(c.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index); +} + +void ContextTest::configurationConstructMove() { + #ifndef MAGNUM_TARGET_GLES + Containers::StringView workaround = "no-layout-qualifiers-on-old-glsl"; + Containers::StringView another = "nv-compressed-block-size-in-bits"; + #elif !defined(MAGNUM_TARGET_WEBGL) + Containers::StringView workaround = "swiftshader-no-empty-egl-context-flags"; + Containers::StringView another = "angle-chatty-shader-compiler"; + #else + /* No general WebGL workarounds to test */ + #endif + + Context::Configuration a; + a.setFlags(Context::Configuration::Flag::VerboseLog) + #ifndef MAGNUM_TARGET_WEBGL + .addDisabledWorkarounds({workaround}) + #endif + .addDisabledExtensions(); + + Context::Configuration b = std::move(a); + CORRADE_COMPARE(UnsignedLong(b.flags()), UnsignedLong(Context::Configuration::Flag::VerboseLog)); + CORRADE_VERIFY(a.disabledWorkarounds().empty()); + CORRADE_VERIFY(a.disabledExtensions().empty()); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE_AS(b.disabledWorkarounds(), + Containers::arrayView({workaround}), + TestSuite::Compare::Container); + #endif + CORRADE_COMPARE(b.disabledExtensions().size(), 1); + CORRADE_COMPARE(b.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index); + + Context::Configuration c; + c.setFlags(Context::Configuration::Flag::QuietLog) + #ifndef MAGNUM_TARGET_WEBGL + .addDisabledWorkarounds({another, another}) + .addDisabledExtensions() + #else + .addDisabledExtensions() + #endif + ; + + c = std::move(b); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE(b.disabledWorkarounds().size(), 2); + #endif + CORRADE_COMPARE(b.disabledExtensions().size(), 2); + CORRADE_COMPARE(UnsignedLong(c.flags()), UnsignedLong(Context::Configuration::Flag::VerboseLog)); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE_AS(c.disabledWorkarounds(), + Containers::arrayView({workaround}), + TestSuite::Compare::Container); + #endif + CORRADE_COMPARE(c.disabledExtensions().size(), 1); + CORRADE_COMPARE(c.disabledExtensions()[0].index(), Extensions::EXT::texture_filter_anisotropic::Index); +} + void ContextTest::constructNoCreate() { { /* Shouldn't crash during construction, shouldn't attempt to access GL, diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index 24b1e06c7..99f34a05d 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -105,7 +105,7 @@ bool AbstractXApplication::tryCreate(const Configuration& configuration, const G _contextHandler->makeCurrent(); /* Return true if the initialization succeeds */ - return _context->tryCreate(); + return _context->tryCreate(glConfiguration); } AbstractXApplication::~AbstractXApplication() { diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index e2745093f..adc4193ef 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -60,7 +60,7 @@ typedef int Bool; #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/GL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Math/Vector2.h" #include "Magnum/Platform/Platform.h" @@ -336,7 +336,7 @@ Double-buffered OpenGL context. @ref Configuration, @ref create(), @ref tryCreate() @todo GLX_ARB_create_context_robustness/EGL_EXT_create_context_robustness */ -class AbstractXApplication::GLConfiguration { +class AbstractXApplication::GLConfiguration: public GL::Context::Configuration { public: explicit GLConfiguration(); ~GLConfiguration(); @@ -350,6 +350,23 @@ class AbstractXApplication::GLConfiguration { return *this; } + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + GLConfiguration& setFlags(Flags flags) { + GL::Context::Configuration::setFlags(flags); + return *this; + } + GLConfiguration& addFlags(Flags flags) { + GL::Context::Configuration::addFlags(flags); + return *this; + } + GLConfiguration& clearFlags(Flags flags) { + GL::Context::Configuration::clearFlags(flags); + return *this; + } + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration) + #endif + private: GL::Version _version; }; diff --git a/src/Magnum/Platform/AndroidApplication.cpp b/src/Magnum/Platform/AndroidApplication.cpp index abc5e983c..b45ea7d77 100644 --- a/src/Magnum/Platform/AndroidApplication.cpp +++ b/src/Magnum/Platform/AndroidApplication.cpp @@ -167,7 +167,7 @@ bool AndroidApplication::tryCreate(const Configuration& configuration, const GLC CORRADE_INTERNAL_ASSERT_OUTPUT(eglMakeCurrent(_display, _surface, _surface, _glContext)); /* Return true if the initialization succeeds */ - return _context->tryCreate(); + return _context->tryCreate(glConfiguration); } Vector2i AndroidApplication::framebufferSize() const { diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index dd12a508d..e09a2e368 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -36,7 +36,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/GL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Math/Vector4.h" #include "Magnum/Platform/Platform.h" @@ -448,7 +448,7 @@ Double-buffered RGBA canvas with depth and stencil buffers. @see @ref AndroidApplication(), @ref Configuration, @ref create(), @ref tryCreate() */ -class AndroidApplication::GLConfiguration { +class AndroidApplication::GLConfiguration: public GL::Context::Configuration { public: /*implicit*/ GLConfiguration(); @@ -504,6 +504,23 @@ class AndroidApplication::GLConfiguration { return *this; } + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + GLConfiguration& setFlags(Flags flags) { + GL::Context::Configuration::setFlags(flags); + return *this; + } + GLConfiguration& addFlags(Flags flags) { + GL::Context::Configuration::addFlags(flags); + return *this; + } + GLConfiguration& clearFlags(Flags flags) { + GL::Context::Configuration::clearFlags(flags); + return *this; + } + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration) + #endif + private: Vector4i _colorBufferSize; Int _depthBufferSize, _stencilBufferSize; diff --git a/src/Magnum/Platform/EmscriptenApplication.cpp b/src/Magnum/Platform/EmscriptenApplication.cpp index 63d8fdeaf..86d826c6c 100644 --- a/src/Magnum/Platform/EmscriptenApplication.cpp +++ b/src/Magnum/Platform/EmscriptenApplication.cpp @@ -450,7 +450,7 @@ bool EmscriptenApplication::tryCreate(const Configuration& configuration, const setupAnimationFrame(!!(configuration.windowFlags() & Configuration::WindowFlag::AlwaysRequestAnimationFrame)); /* Return true if the initialization succeeds */ - return _context->tryCreate(); + return _context->tryCreate(glConfiguration); } #endif @@ -770,7 +770,10 @@ void EmscriptenApplication::textInputEvent(TextInputEvent&) {} #ifdef MAGNUM_TARGET_GL EmscriptenApplication::GLConfiguration::GLConfiguration(): _colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0}, - _sampleCount{0} {} + _sampleCount{0} +{ + addFlags(Flag::EnableExtensionsByDefault); +} #endif int EmscriptenApplication::exec() { diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index 1f16dfbb9..3d7d0b81f 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -40,7 +40,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/GL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Math/Vector4.h" #include "Magnum/Platform/Platform.h" @@ -926,14 +926,15 @@ The created context is always with a double-buffered OpenGL context. @see @ref EmscriptenApplication(), @ref Configuration, @ref create(), @ref tryCreate() */ -class EmscriptenApplication::GLConfiguration { +class EmscriptenApplication::GLConfiguration: public GL::Context::Configuration { public: /** * @brief Context flag * + * Includes also everything from @ref GL::Context::Configuration::Flag. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ - enum class Flag: Int { + enum class Flag: UnsignedLong { /** * Premultiplied alpha. If set, the alpha channel of the rendering * context will be treated as representing premultiplied alpha @@ -987,7 +988,25 @@ class EmscriptenApplication::GLConfiguration { * Proxy content to main thread. For more details, see the * [Emscripten API reference](https://emscripten.org/docs/api_reference/html5.h.html#c.EmscriptenWebGLContextAttributes.proxyContextToMainThread). */ - ProxyContextToMainThread = 1 << 7 + ProxyContextToMainThread = 1 << 7, + + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) }; /** @@ -1000,7 +1019,9 @@ class EmscriptenApplication::GLConfiguration { /*implicit*/ GLConfiguration(); /** @brief Context flags */ - Flags flags() const { return _flags; } + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } /** * @brief Set context flags @@ -1012,7 +1033,7 @@ class EmscriptenApplication::GLConfiguration { * @see @ref GL::Context::flags() */ GLConfiguration& setFlags(Flags flags) { - _flags = flags; + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -1025,7 +1046,7 @@ class EmscriptenApplication::GLConfiguration { * @see @ref clearFlags() */ GLConfiguration& addFlags(Flags flags) { - _flags |= flags; + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -1038,7 +1059,7 @@ class EmscriptenApplication::GLConfiguration { * @see @ref addFlags() */ GLConfiguration& clearFlags(Flags flags) { - _flags &= ~flags; + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -1112,12 +1133,15 @@ class EmscriptenApplication::GLConfiguration { return *this; } + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration) + #endif + private: Vector4i _colorBufferSize; Int _depthBufferSize, _stencilBufferSize; Int _sampleCount; - - Flags _flags{Flag::EnableExtensionsByDefault}; }; CORRADE_ENUMSET_OPERATORS(EmscriptenApplication::GLConfiguration::Flags) diff --git a/src/Magnum/Platform/GLContext.h b/src/Magnum/Platform/GLContext.h index fda6110ac..dd372478e 100644 --- a/src/Magnum/Platform/GLContext.h +++ b/src/Magnum/Platform/GLContext.h @@ -58,26 +58,29 @@ class GLContext: public GL::Context { * @brief Constructor * * Equivalent to calling @ref GLContext(NoCreateT, Int, const char**) - * followed by @ref create(). + * followed by @ref create(const Configuration&). */ - explicit GLContext(Int argc, const char** argv): GLContext{NoCreate, argc, argv} { create(); } + explicit GLContext(Int argc, const char** argv, const Configuration& configuration = {}): GLContext{NoCreate, argc, argv} { + create(configuration); + } /** @overload */ - explicit GLContext(Int argc, char** argv): GLContext{argc, const_cast(argv)} {} + explicit GLContext(Int argc, char** argv, const Configuration& configuration = {}): GLContext{argc, const_cast(argv), configuration} {} /** @overload */ - explicit GLContext(Int argc, std::nullptr_t argv): GLContext{argc, static_cast(argv)} {} + explicit GLContext(Int argc, std::nullptr_t argv, const Configuration& configuration = {}): GLContext{argc, static_cast(argv), configuration} {} /** * @brief Default constructor * - * Equivalent to passing @cpp {0, nullptr} @ce to - * @ref GLContext(Int, const char**). Even if the command-line options - * are not propagated, it's still possible to affect the renderer - * behavior from the environment. See @ref GL-Context-command-line for - * more information. + * Equivalent to passing @cpp {0, nullptr, configuration} @ce to + * @ref GLContext(Int, const char**, const Configuration&). Even if the + * command-line options are not propagated, it's still possible to + * affect the setup behavior from the environment or by passing a + * @relativeref{GL::Context,Configuration} instance. See + * @ref GL-Context-usage for more information. */ - explicit GLContext(): GLContext{0, nullptr} {} + explicit GLContext(const Configuration& configuration = {}): GLContext{0, nullptr, configuration} {} /** * @brief Construct without creating the context @@ -85,7 +88,7 @@ class GLContext: public GL::Context { * Parses command-line arguments and sets @ref version() to * @ref GL::Version::None, everything else is left in an empty state. * Use @ref create() or @ref tryCreate() to create the context. - * @see @ref GLContext(Int, const char**) + * @see @ref GLContext(Int, const char**, const Configuration&) */ explicit GLContext(NoCreateT, Int argc, const char** argv): #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -118,8 +121,9 @@ class GLContext: public GL::Context { * Equivalent to passing @cpp {NoCreate, 0, nullptr} @ce to * @ref GLContext(NoCreateT, Int, const char**). Even if the * command-line options are not propagated, it's still possible to - * affect the renderer behavior from the environment. See - * @ref GL-Context-command-line for more information. + * affect the renderer behavior from the environment or by passing + * a @relativeref{GL::Context,Configuration} instance to @ref create() + * or @ref tryCreate(). See @ref GL-Context-usage for more information. */ explicit GLContext(NoCreateT): GLContext{NoCreate, 0, nullptr} {} @@ -133,13 +137,15 @@ class GLContext: public GL::Context { * detected version is unsupported or any other error occurs, a message * is printed to output and the application exits. See @ref tryCreate() * for an alternative. - * @see @ref GLContext(Int, char**), @ref GL-Context-command-line, - * @fn_gl{Get} with @def_gl{MAJOR_VERSION}, + * @see @ref GLContext(Int, char**, const Configuration&), + * @ref GL-Context-usage, @fn_gl{Get} with @def_gl{MAJOR_VERSION}, * @def_gl{MINOR_VERSION}, @def_gl{CONTEXT_FLAGS}, * @def_gl{NUM_EXTENSIONS}, @fn_gl{GetString} with * @def_gl{EXTENSIONS} */ - void create() { return GL::Context::create(); } + void create(const Configuration& configuration = Configuration{}) { + return GL::Context::create(configuration); + } /** * @brief Try to create the context @@ -147,7 +153,9 @@ class GLContext: public GL::Context { * Unlike @ref create(), instead of exiting prints a message to error * output and returns `false` on error. */ - bool tryCreate() { return GL::Context::tryCreate(); } + bool tryCreate(const Configuration& configuration = Configuration{}) { + return GL::Context::tryCreate(configuration); + } }; }} diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 0fcd147c7..4dc455378 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -578,7 +578,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf glfwMakeContextCurrent(_window); /* Destroy everything when the Magnum context creation fails */ - if(!_context->tryCreate()) { + if(!_context->tryCreate(glConfiguration)) { glfwDestroyWindow(_window); _window = nullptr; } @@ -894,13 +894,12 @@ void GlfwApplication::stopTextInput() { #ifdef MAGNUM_TARGET_GL GlfwApplication::GLConfiguration::GLConfiguration(): _colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0}, - _sampleCount{0}, _version{GL::Version::None}, + _sampleCount{0}, _version{GL::Version::None}, _srgbCapable{false} +{ #ifndef MAGNUM_TARGET_GLES - _flags{Flag::ForwardCompatible}, - #else - _flags{}, + addFlags(Flag::ForwardCompatible); #endif - _srgbCapable{false} {} +} GlfwApplication::GLConfiguration::~GLConfiguration() = default; #endif diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index c45d403ce..b0135b8f8 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -43,7 +43,7 @@ #include "Magnum/Platform/Platform.h" #ifdef MAGNUM_TARGET_GL -#include "Magnum/GL/GL.h" +#include "Magnum/GL/Context.h" #endif #ifndef DOXYGEN_GENERATING_OUTPUT @@ -777,14 +777,15 @@ The created window is always with a double-buffered OpenGL context. @see @ref GlfwApplication(), @ref create(), @ref tryCreate() */ -class GlfwApplication::GLConfiguration { +class GlfwApplication::GLConfiguration: public GL::Context::Configuration { public: /** * @brief Context flag * + * Includes also everything from @ref GL::Context::Configuration::Flag. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ - enum class Flag: UnsignedByte { + enum class Flag: UnsignedLong { #ifndef MAGNUM_TARGET_GLES /** * Forward compatible context @@ -807,13 +808,32 @@ class GlfwApplication::GLConfiguration { #endif /** - * Debug context. Enabled automatically if the - * `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" + * Debug context. Enabled automatically if supported by the driver + * and the @ref Flag::GpuValidation flag is set or if the + * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" * is present. */ Debug = 1 << 2, - Stereo = 1 << 3 /**< Stereo rendering */ + Stereo = 1 << 3, /**< Stereo rendering */ + + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) }; /** @@ -827,7 +847,9 @@ class GlfwApplication::GLConfiguration { ~GLConfiguration(); /** @brief Context flags */ - Flags flags() const { return _flags; } + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } /** * @brief Set context flags @@ -839,7 +861,7 @@ class GlfwApplication::GLConfiguration { * @see @ref GL::Context::flags() */ GLConfiguration& setFlags(Flags flags) { - _flags = flags; + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -852,7 +874,7 @@ class GlfwApplication::GLConfiguration { * @see @ref clearFlags() */ GLConfiguration& addFlags(Flags flags) { - _flags |= flags; + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -865,7 +887,7 @@ class GlfwApplication::GLConfiguration { * @see @ref addFlags() */ GLConfiguration& clearFlags(Flags flags) { - _flags &= ~flags; + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -958,12 +980,16 @@ class GlfwApplication::GLConfiguration { return *this; } + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration) + #endif + private: Vector4i _colorBufferSize; Int _depthBufferSize, _stencilBufferSize; Int _sampleCount; GL::Version _version; - Flags _flags; bool _srgbCapable; }; diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index ccec3f2d3..0c59ac235 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -484,7 +484,8 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); #endif - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glFlags)); + /* Mask out the upper 32bits used for other flags */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(UnsignedLong(glFlags) & 0xffffffffu)); /* Request usable version otherwise */ } else { @@ -501,7 +502,8 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); #endif SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glFlags)); + /* Mask out the upper 32bits used for other flags */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(UnsignedLong(glFlags) & 0xffffffffu)); #else /* For ES the major context version is compile-time constant */ #ifdef MAGNUM_TARGET_GLES3 @@ -579,8 +581,10 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); /* Discard the ForwardCompatible flag for the fallback. Having it set makes the fallback context creation fail on Mesa's Zink (which is - just 2.1) and I assume on others as well. */ - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(glFlags) & int(~GLConfiguration::Flag::ForwardCompatible)); + just 2.1) and I assume on others as well. + + Also mask out the upper 32bits used for other flags. */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, int(UnsignedLong(glFlags & ~GLConfiguration::Flag::ForwardCompatible) & 0xffffffffu)); if(!(_window = SDL_CreateWindow(configuration.title().data(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, @@ -666,7 +670,7 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf #endif /* Destroy everything also when the Magnum context creation fails */ - if(!_context->tryCreate()) { + if(!_context->tryCreate(glConfiguration)) { #ifndef CORRADE_TARGET_EMSCRIPTEN SDL_GL_DeleteContext(_glContext); SDL_DestroyWindow(_window); @@ -1184,15 +1188,13 @@ Sdl2Application::GLConfiguration::GLConfiguration(): _colorBufferSize{8, 8, 8, 8}, _depthBufferSize{24}, _stencilBufferSize{0}, _sampleCount(0) #ifndef CORRADE_TARGET_EMSCRIPTEN - , _version(GL::Version::None), - #ifndef MAGNUM_TARGET_GLES - _flags{Flag::ForwardCompatible}, - #else - _flags{}, + , _version{GL::Version::None}, _srgbCapable{false} #endif - _srgbCapable{false} +{ + #ifndef MAGNUM_TARGET_GLES + addFlags(Flag::ForwardCompatible); #endif - {} +} Sdl2Application::GLConfiguration::~GLConfiguration() = default; #endif diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 91fb46abb..b35d10b5f 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -42,7 +42,7 @@ #include "Magnum/Platform/Platform.h" #ifdef MAGNUM_TARGET_GL -#include "Magnum/GL/GL.h" +#include "Magnum/GL/Context.h" #endif #ifdef CORRADE_TARGET_WINDOWS /* Windows version of SDL2 redefines main(), we don't want that */ @@ -1229,20 +1229,19 @@ The created window is always with a double-buffered OpenGL context. @see @ref Sdl2Application(), @ref create(), @ref tryCreate() */ -class Sdl2Application::GLConfiguration { +class Sdl2Application::GLConfiguration: public GL::Context::Configuration { public: - #ifndef CORRADE_TARGET_EMSCRIPTEN /** * @brief Context flag * + * Includes also everything from @ref GL::Context::Configuration::Flag. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag - * @requires_gles Context flags are not available in WebGL. */ - enum class Flag: int { + enum class Flag: UnsignedLong { + #ifndef CORRADE_TARGET_EMSCRIPTEN #ifndef MAGNUM_TARGET_GLES /** - * Forward compatible context - * + * Forward compatible context. * @requires_gl Core/compatibility profile distinction and forward * compatibility applies only to desktop GL. */ @@ -1250,38 +1249,60 @@ class Sdl2Application::GLConfiguration { #endif /** - * Debug context. Enabled automatically if the - * `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" + * Debug context. Enabled automatically if supported by the driver + * and the @ref Flag::GpuValidation flag is set or if the + * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" * is present. + * @requires_gles Context flags are not available in WebGL. */ Debug = SDL_GL_CONTEXT_DEBUG_FLAG, - /** Context with robust access */ + /** + * Context with robust access. + * @requires_gles Context flags are not available in WebGL. + */ RobustAccess = SDL_GL_CONTEXT_ROBUST_ACCESS_FLAG, - /** Context with reset isolation */ - ResetIsolation = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG + /** + * Context with reset isolation. + * @requires_gles Context flags are not available in WebGL. + */ + ResetIsolation = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG, + #endif + + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) }; /** * @brief Context flags * * @see @ref setFlags(), @ref GL::Context::Flags - * @requires_gles Context flags are not available in WebGL. */ typedef Containers::EnumSet Flags; - #endif explicit GLConfiguration(); ~GLConfiguration(); - #ifndef CORRADE_TARGET_EMSCRIPTEN - /** - * @brief Context flags - * - * @requires_gles Context flags are not available in WebGL. - */ - Flags flags() const { return _flags; } + /** @brief Context flags */ + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } /** * @brief Set context flags @@ -1291,10 +1312,9 @@ class Sdl2Application::GLConfiguration { * on OpenGL ES. To avoid clearing default flags by accident, prefer to * use @ref addFlags() and @ref clearFlags() instead. * @see @ref GL::Context::flags() - * @requires_gles Context flags are not available in WebGL. */ GLConfiguration& setFlags(Flags flags) { - _flags = flags; + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -1305,10 +1325,9 @@ class Sdl2Application::GLConfiguration { * Unlike @ref setFlags(), ORs the flags with existing instead of * replacing them. Useful for preserving the defaults. * @see @ref clearFlags() - * @requires_gles Context flags are not available in WebGL. */ GLConfiguration& addFlags(Flags flags) { - _flags |= flags; + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -1319,13 +1338,13 @@ class Sdl2Application::GLConfiguration { * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing * instead of replacing them. Useful for removing default flags. * @see @ref addFlags() - * @requires_gles Context flags are not available in WebGL. */ GLConfiguration& clearFlags(Flags flags) { - _flags &= ~flags; + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } + #ifndef CORRADE_TARGET_EMSCRIPTEN /** * @brief Context version * @@ -1434,13 +1453,17 @@ class Sdl2Application::GLConfiguration { } #endif + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration) + #endif + private: Vector4i _colorBufferSize; Int _depthBufferSize, _stencilBufferSize; Int _sampleCount; #ifndef CORRADE_TARGET_EMSCRIPTEN GL::Version _version; - Flags _flags; bool _srgbCapable; #endif }; diff --git a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp index 4de4bdb09..e330277e4 100644 --- a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp +++ b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp @@ -153,6 +153,7 @@ EmscriptenApplicationTest::EmscriptenApplicationTest(const Arguments& arguments) Utility::Arguments args; args.addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); /* Useful for bisecting Emscripten regressions, because they happen WAY TOO @@ -167,9 +168,12 @@ EmscriptenApplicationTest::EmscriptenApplicationTest(const Arguments& arguments) return; } - create(Configuration{}.setWindowFlags(Configuration::WindowFlag::Resizable) - //, GLConfiguration{}.setFlags({}) - ); + Configuration conf; + conf.setWindowFlags(Configuration::WindowFlag::Resizable); + if(args.isSet("quiet")) + create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog)); + else + create(conf); Debug{} << "window size" << windowSize() #ifdef MAGNUM_TARGET_GL diff --git a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp index c9da740f6..bfb8d4447 100644 --- a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp +++ b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp @@ -108,6 +108,9 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform:: .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") .addBooleanOption("borderless").setHelp("borderless", "no window decoration") .addBooleanOption("always-on-top").setHelp("always-on-top", "always on top") + #ifdef MAGNUM_TARGET_GL + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + #endif .parse(arguments.argc, arguments.argv); if(args.isSet("exit-immediately")) { @@ -123,7 +126,14 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform:: conf.addWindowFlags(Configuration::WindowFlag::Borderless); if(args.isSet("always-on-top")) conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop); - create(conf); + #ifdef MAGNUM_TARGET_GL + if(args.isSet("quiet")) { + create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog)); + } else + #endif + { + create(conf); + } /* For testing resize events */ Debug{} << "window size" << windowSize() diff --git a/src/Magnum/Platform/Test/GlxApplicationTest.cpp b/src/Magnum/Platform/Test/GlxApplicationTest.cpp index a82d1f7c3..17e27168f 100644 --- a/src/Magnum/Platform/Test/GlxApplicationTest.cpp +++ b/src/Magnum/Platform/Test/GlxApplicationTest.cpp @@ -42,6 +42,7 @@ GlxApplicationTest::GlxApplicationTest(const Arguments& arguments): Platform::Ap Utility::Arguments args; args.addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); if(args.isSet("exit-immediately")) { @@ -49,7 +50,10 @@ GlxApplicationTest::GlxApplicationTest(const Arguments& arguments): Platform::Ap return; } - create(Configuration{}); + if(args.isSet("quiet")) + create(Configuration{}, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog)); + else + create(); } }}}} diff --git a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp index a12f36446..6565311ea 100644 --- a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp +++ b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp @@ -165,6 +165,9 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform:: .addBooleanOption("always-on-top").setHelp("always-on-top", "always on top") #endif #endif + #ifdef MAGNUM_TARGET_GL + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + #endif .parse(arguments.argc, arguments.argv); if(args.isSet("exit-immediately")) { @@ -184,7 +187,14 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform:: conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop); #endif #endif - create(conf); + #ifdef MAGNUM_TARGET_GL + if(args.isSet("quiet")) { + create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog)); + } else + #endif + { + create(conf); + } /* For testing resize events */ Debug{} << "window size" << windowSize() diff --git a/src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp index e3f83a1a4..a90c98eac 100644 --- a/src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp @@ -23,15 +23,29 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Magnum/Platform/WindowlessCglApplication.h" namespace Magnum { namespace Platform { namespace Test { namespace { struct WindowlessCglApplicationTest: Platform::WindowlessApplication { - explicit WindowlessCglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} + explicit WindowlessCglApplicationTest(const Arguments& arguments); int exec() override { return 0; } }; +WindowlessCglApplicationTest::WindowlessCglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { + Utility::Arguments args; + args.addSkippedPrefix("magnum", "engine-specific options") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .parse(arguments.argc, arguments.argv); + + if(args.isSet("quiet")) + createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); + else + createContext(); +} + }}}} MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessCglApplicationTest) diff --git a/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp index c40029231..d6464e6fd 100644 --- a/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp @@ -23,15 +23,29 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Magnum/Platform/WindowlessEglApplication.h" namespace Magnum { namespace Platform { namespace Test { namespace { struct WindowlessEglApplicationTest: Platform::WindowlessApplication { - explicit WindowlessEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} + explicit WindowlessEglApplicationTest(const Arguments& arguments); int exec() override { return 0; } }; +WindowlessEglApplicationTest::WindowlessEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { + Utility::Arguments args; + args.addSkippedPrefix("magnum", "engine-specific options") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .parse(arguments.argc, arguments.argv); + + if(args.isSet("quiet")) + createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); + else + createContext(); +} + }}}} MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessEglApplicationTest) diff --git a/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp index 58b859549..e75b3d9c5 100644 --- a/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp @@ -23,15 +23,29 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Magnum/Platform/WindowlessGlxApplication.h" namespace Magnum { namespace Platform { namespace Test { namespace { struct WindowlessGlxApplicationTest: Platform::WindowlessApplication { - explicit WindowlessGlxApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} + explicit WindowlessGlxApplicationTest(const Arguments& arguments); int exec() override { return 0; } }; +WindowlessGlxApplicationTest::WindowlessGlxApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { + Utility::Arguments args; + args.addSkippedPrefix("magnum", "engine-specific options") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .parse(arguments.argc, arguments.argv); + + if(args.isSet("quiet")) + createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); + else + createContext(); +} + }}}} MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessGlxApplicationTest) diff --git a/src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp index 8ba527548..a1f042616 100644 --- a/src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp @@ -23,15 +23,29 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Magnum/Platform/WindowlessIosApplication.h" namespace Magnum { namespace Platform { namespace Test { namespace { struct WindowlessIosApplicationTest: Platform::WindowlessApplication { - explicit WindowlessIosApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} + explicit WindowlessIosApplicationTest(const Arguments& arguments); int exec() override { return 0; } }; +WindowlessIosApplicationTest::WindowlessIosApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { + Utility::Arguments args; + args.addSkippedPrefix("magnum", "engine-specific options") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .parse(arguments.argc, arguments.argv); + + if(args.isSet("quiet")) + createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); + else + createContext(); +} + }}}} MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessIosApplicationTest) diff --git a/src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp index 1a79e7976..82b7baaa2 100644 --- a/src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp @@ -23,15 +23,29 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Magnum/Platform/WindowlessWglApplication.h" namespace Magnum { namespace Platform { namespace Test { namespace { struct WindowlessWglApplicationTest: Platform::WindowlessApplication { - explicit WindowlessWglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} + explicit WindowlessWglApplicationTest(const Arguments& arguments); int exec() override { return 0; } }; +WindowlessWglApplicationTest::WindowlessWglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { + Utility::Arguments args; + args.addSkippedPrefix("magnum", "engine-specific options") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .parse(arguments.argc, arguments.argv); + + if(args.isSet("quiet")) + createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); + else + createContext(); +} + }}}} MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessWglApplicationTest) diff --git a/src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp index 65b5745c7..9bc627507 100644 --- a/src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp @@ -23,15 +23,29 @@ DEALINGS IN THE SOFTWARE. */ +#include + #include "Magnum/Platform/WindowlessWindowsEglApplication.h" namespace Magnum { namespace Platform { namespace Test { namespace { struct WindowlessWindowsEglApplicationTest: Platform::WindowlessApplication { - explicit WindowlessWindowsEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments} {} + explicit WindowlessWindowsEglApplicationTest(const Arguments& arguments); int exec() override { return 0; } }; +WindowlessWindowsEglApplicationTest::WindowlessWindowsEglApplicationTest(const Arguments& arguments): Platform::WindowlessApplication{arguments, NoCreate} { + Utility::Arguments args; + args.addSkippedPrefix("magnum", "engine-specific options") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .parse(arguments.argc, arguments.argv); + + if(args.isSet("quiet")) + createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); + else + createContext(); +} + }}}} MAGNUM_WINDOWLESSAPPLICATION_MAIN(Magnum::Platform::Test::WindowlessWindowsEglApplicationTest) diff --git a/src/Magnum/Platform/Test/XEglApplicationTest.cpp b/src/Magnum/Platform/Test/XEglApplicationTest.cpp index 103961972..739776e74 100644 --- a/src/Magnum/Platform/Test/XEglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/XEglApplicationTest.cpp @@ -42,6 +42,7 @@ XEglApplicationTest::XEglApplicationTest(const Arguments& arguments): Platform:: Utility::Arguments args; args.addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("exit-immediately").setHelp("exit-immediately", "exit the application immediately from the constructor, to test that the app doesn't run any event handlers after") + .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); if(args.isSet("exit-immediately")) { @@ -49,10 +50,12 @@ XEglApplicationTest::XEglApplicationTest(const Arguments& arguments): Platform:: return; } - create(Configuration{}); + if(args.isSet("quiet")) + create(Configuration{}, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog)); + else + create(); } - }}}} MAGNUM_APPLICATION_MAIN(Magnum::Platform::Test::XEglApplicationTest) diff --git a/src/Magnum/Platform/WindowlessCglApplication.cpp b/src/Magnum/Platform/WindowlessCglApplication.cpp index 9ac9395be..3fb0d1b7e 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.cpp +++ b/src/Magnum/Platform/WindowlessCglApplication.cpp @@ -36,7 +36,7 @@ namespace Magnum { namespace Platform { -WindowlessCglContext::WindowlessCglContext(const Configuration & configuration, GLContext*) { +WindowlessCglContext::WindowlessCglContext(const Configuration& configuration, GLContext*) { int formatCount; CGLPixelFormatAttribute attributes32[] = { kCGLPFAAccelerated, @@ -128,7 +128,7 @@ bool WindowlessCglApplication::tryCreateContext(const Configuration& configurati CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false); WindowlessCglContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index 271e0c70f..07e908bff 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -39,7 +39,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/OpenGL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Platform/Platform.h" #ifndef DOXYGEN_GENERATING_OUTPUT @@ -164,10 +164,8 @@ class WindowlessCglContext { @ref WindowlessCglApplication::createContext(), @ref WindowlessCglApplication::tryCreateContext() */ -class WindowlessCglContext::Configuration { +class WindowlessCglContext::Configuration: public GL::Context::Configuration { public: - constexpr /*implicit*/ Configuration() {} - /** * @brief Create a shared context * @return Reference to self (for method chaining) @@ -192,6 +190,23 @@ class WindowlessCglContext::Configuration { */ CGLContextObj sharedContext() const { return _sharedContext; } + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + Configuration& setFlags(Flags flags) { + GL::Context::Configuration::setFlags(flags); + return *this; + } + Configuration& addFlags(Flags flags) { + GL::Context::Configuration::addFlags(flags); + return *this; + } + Configuration& clearFlags(Flags flags) { + GL::Context::Configuration::clearFlags(flags); + return *this; + } + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration) + #endif + private: CGLContextObj _sharedContext = nullptr; }; diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 41b2e5faa..1eb1154b3 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -328,8 +328,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G #endif #ifndef MAGNUM_TARGET_WEBGL /* Needs to be last because we're zeroing this out for SwiftShader (see - below) */ - EGL_CONTEXT_FLAGS_KHR, EGLint(flags), + below). + + Also mask out the upper 32bits used for other flags. */ + EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu), #endif EGL_NONE }; @@ -369,8 +371,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G const EGLint fallbackAttributes[] = { /* Discard the ForwardCompatible flag for the fallback. Having it set makes the fallback context creation fail on Mesa's Zink - (which is just 2.1) and I assume on others as well. */ - EGL_CONTEXT_FLAGS_KHR, GLint(flags & ~Configuration::Flag::ForwardCompatible), + (which is just 2.1) and I assume on others as well. + + Also mask out the upper 32bits used for other flags. */ + EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), EGL_NONE }; _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes); @@ -409,8 +413,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G /* Discard the ForwardCompatible flag for the fallback. Compared to the above case of a 2.1 fallback it's not really needed here (AFAIK it works in both cases), but let's be - consistent. */ - EGL_CONTEXT_FLAGS_KHR, GLint(flags & ~Configuration::Flag::ForwardCompatible), + consistent. + + Also mask out the upper 32bits used for other flags. */ + EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), EGL_NONE }; _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes); @@ -519,12 +525,14 @@ bool WindowlessEglContext::release() { } WindowlessEglContext::Configuration::Configuration() + #ifndef MAGNUM_TARGET_WEBGL + : _device{} + #endif +{ #ifndef MAGNUM_TARGET_GLES - : _flags{Flag::ForwardCompatible}, _device{} - #elif !defined(MAGNUM_TARGET_WEBGL) - : _flags{}, _device{} + addFlags(Flag::ForwardCompatible); #endif - {} +} #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments): WindowlessEglApplication{arguments, Configuration{}} {} @@ -574,7 +582,7 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati #endif WindowlessEglContext glContext{mergedConfiguration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index ec17eb69a..22340bfd1 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -58,7 +58,7 @@ typedef int Bool; #endif #include "Magnum/Magnum.h" -#include "Magnum/GL/OpenGL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Tags.h" #include "Magnum/Platform/Platform.h" @@ -179,16 +179,16 @@ class WindowlessEglContext { @ref WindowlessEglApplication::createContext(), @ref WindowlessEglApplication::tryCreateContext() */ -class WindowlessEglContext::Configuration { +class WindowlessEglContext::Configuration: public GL::Context::Configuration { public: - #ifndef MAGNUM_TARGET_WEBGL /** * @brief Context flag * + * Includes also everything from @ref GL::Context::Configuration::Flag. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag - * @requires_gles Context flags are not available in WebGL. */ - enum class Flag: int { + enum class Flag: UnsignedLong { + #ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_GLES /** * Forward compatible context @@ -200,31 +200,47 @@ class WindowlessEglContext::Configuration { #endif /** - * Debug context. Enabled automatically if the - * `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" + * Debug context. Enabled automatically if supported by the driver + * and the @ref Flag::GpuValidation flag is set or if the + * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" * is present. + * @requires_gles Context flags are not available in WebGL. + */ + Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, + #endif + + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest */ - Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) }; /** * @brief Context flags * * @see @ref setFlags(), @ref Context::Flags - * @requires_gles Context flags are not available in WebGL. */ typedef Containers::EnumSet Flags; - #endif /*implicit*/ Configuration(); - #ifndef MAGNUM_TARGET_WEBGL - /** - * @brief Context flags - * - * @requires_gles Context flags are not available in WebGL. - */ - Flags flags() const { return _flags; } + /** @brief Context flags */ + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } /** * @brief Set context flags @@ -234,10 +250,9 @@ class WindowlessEglContext::Configuration { * on OpenGL ES. To avoid clearing default flags by accident, prefer to * use @ref addFlags() and @ref clearFlags() instead. * @see @ref GL::Context::flags() - * @requires_gles Context flags are not available in WebGL. */ Configuration& setFlags(Flags flags) { - _flags = flags; + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -248,10 +263,9 @@ class WindowlessEglContext::Configuration { * Unlike @ref setFlags(), ORs the flags with existing instead of * replacing them. Useful for preserving the defaults. * @see @ref clearFlags() - * @requires_gles Context flags are not available in WebGL. */ Configuration& addFlags(Flags flags) { - _flags |= flags; + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -262,13 +276,13 @@ class WindowlessEglContext::Configuration { * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing * instead of replacing them. Useful for removing default flags. * @see @ref addFlags() - * @requires_gles Context flags are not available in WebGL. */ Configuration& clearFlags(Flags flags) { - _flags &= ~flags; + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } + #ifndef MAGNUM_TARGET_WEBGL /** * @brief Device ID to use * @m_since{2019,10} @@ -364,9 +378,13 @@ class WindowlessEglContext::Configuration { EGLContext sharedContext() const { return _sharedContext; } #endif + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration) + #endif + private: #ifndef MAGNUM_TARGET_WEBGL - Flags _flags; UnsignedInt _device; /* Assumes that you can't have 2^32 - 1 GPUs */ UnsignedInt _cudaDevice = ~UnsignedInt{}; @@ -503,7 +521,7 @@ can override that either with @ref Configuration::setDevice() or using a `--magnum-device` command-line option (and the `MAGNUM_DEVICE` environment variable). Unfortunately EGL doesn't provide any reasonable way to enumerate or filter named devices, so the best you can do is checking reported device count -printed by the `--magnum-log verbose` @ref GL-Context-command-line "command-line option", +printed by the `--magnum-log verbose` @ref GL-Context-usage-command-line "command-line option", and then going from `0` up to figure out the desired device ID. On systems with NVIDIA GPUs and CUDA, it's possible to directly select a @@ -521,7 +539,7 @@ Systems running Mesa 19.2 (which has the above extensions) that also have `libEGL_nvidia.so` installed (for example as a CUDA dependency) may fail to create the context with the following error (with additional output produced when the `--magnum-gpu-validation` -@ref GL-Context-command-line "command-line option" is enabled): +@ref GL-Context-usage-command-line "command-line option" is enabled): @m_class{m-console-wrap} diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index e010ef495..d94ea434c 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -126,12 +126,14 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura #endif GLX_CONTEXT_MINOR_VERSION_ARB, 0, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, - GLX_CONTEXT_FLAGS_ARB, GLint(flags), + /* Mask out the upper 32bits used for other flags */ + GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), #else GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 1, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - GLX_CONTEXT_FLAGS_ARB, GLint(flags), + /* Mask out the upper 32bits used for other flags */ + GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), #endif 0 }; @@ -155,8 +157,10 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura const GLint fallbackContextAttributes[] = { /* Discard the ForwardCompatible flag for the fallback. Having it set makes the fallback context creation fail on Mesa's Zink - (which is just 2.1) and I assume on others as well. */ - GLX_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), + (which is just 2.1) and I assume on others as well. + + Also mask out the upper 32bits used for other flags. */ + GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 0 }; { @@ -198,8 +202,10 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura /* Discard the ForwardCompatible flag for the fallback. Compared to the above case of a 2.1 fallback it's not really needed here (AFAIK it works in both cases), but let's be - consistent. */ - GLX_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), + consistent. + + Also mask out the upper 32bits used for other flags. */ + GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 0 }; { @@ -267,13 +273,11 @@ bool WindowlessGlxContext::release() { return false; } -WindowlessGlxContext::Configuration::Configuration(): +WindowlessGlxContext::Configuration::Configuration() { #ifndef MAGNUM_TARGET_GLES - _flags{Flag::ForwardCompatible} - #else - _flags{} + addFlags(Flag::ForwardCompatible); #endif - {} +} #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments): WindowlessGlxApplication{arguments, Configuration{}} {} @@ -295,7 +299,7 @@ bool WindowlessGlxApplication::tryCreateContext(const Configuration& configurati CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false); WindowlessGlxContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 9577f2197..1c1b0f85b 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -39,7 +39,7 @@ /* Include our GL headers first to avoid conflicts */ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/OpenGL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Platform/Platform.h" #include @@ -185,14 +185,15 @@ class WindowlessGlxContext { @ref WindowlessGlxApplication::createContext(), @ref WindowlessGlxApplication::tryCreateContext() */ -class WindowlessGlxContext::Configuration { +class WindowlessGlxContext::Configuration: public GL::Context::Configuration { public: /** * @brief Context flag * + * Includes also everything from @ref GL::Context::Configuration::Flag. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ - enum class Flag: int { + enum class Flag: UnsignedLong { #ifndef MAGNUM_TARGET_GLES /** * Forward compatible context @@ -204,11 +205,30 @@ class WindowlessGlxContext::Configuration { #endif /** - * Debug context. Enabled automatically if the - * `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" + * Debug context. Enabled automatically if supported by the driver + * and the @ref Flag::GpuValidation flag is set or if the + * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" * is present. */ - Debug = GLX_CONTEXT_DEBUG_BIT_ARB + Debug = GLX_CONTEXT_DEBUG_BIT_ARB, + + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) }; /** @@ -221,7 +241,9 @@ class WindowlessGlxContext::Configuration { /*implicit*/ Configuration(); /** @brief Context flags */ - Flags flags() const { return _flags; } + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } /** * @brief Set context flags @@ -233,7 +255,7 @@ class WindowlessGlxContext::Configuration { * @see @ref GL::Context::flags() */ Configuration& setFlags(Flags flags) { - _flags = flags; + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -246,7 +268,7 @@ class WindowlessGlxContext::Configuration { * @see @ref clearFlags() */ Configuration& addFlags(Flags flags) { - _flags |= flags; + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -259,7 +281,7 @@ class WindowlessGlxContext::Configuration { * @see @ref addFlags() */ Configuration& clearFlags(Flags flags) { - _flags &= ~flags; + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -287,8 +309,12 @@ class WindowlessGlxContext::Configuration { */ GLXContext sharedContext() const { return _sharedContext; } + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration) + #endif + private: - Flags _flags; GLXContext _sharedContext = nullptr; }; diff --git a/src/Magnum/Platform/WindowlessIosApplication.h b/src/Magnum/Platform/WindowlessIosApplication.h index 2e922fc94..fdfb7cca2 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.h +++ b/src/Magnum/Platform/WindowlessIosApplication.h @@ -37,7 +37,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/OpenGL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Platform/Platform.h" #ifdef __OBJC__ @@ -154,9 +154,25 @@ class WindowlessIosContext { @ref WindowlessIosApplication::createContext(), @ref WindowlessIosApplication::tryCreateContext() */ -class WindowlessIosContext::Configuration { +class WindowlessIosContext::Configuration: public GL::Context::Configuration { public: - constexpr /*implicit*/ Configuration() {} + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + Configuration& setFlags(Flags flags) { + GL::Context::Configuration::setFlags(flags); + return *this; + } + Configuration& addFlags(Flags flags) { + GL::Context::Configuration::addFlags(flags); + return *this; + } + Configuration& clearFlags(Flags flags) { + GL::Context::Configuration::clearFlags(flags); + return *this; + } + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration) + #endif + }; /** diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 2dd1bbc29..76985b49b 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -139,12 +139,14 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G #endif WGL_CONTEXT_MINOR_VERSION_ARB, 0, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT, - WGL_CONTEXT_FLAGS_ARB, GLint(flags), + /* Mask out the upper 32bits used for other flags */ + WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), #else WGL_CONTEXT_MAJOR_VERSION_ARB, 3, WGL_CONTEXT_MINOR_VERSION_ARB, 1, WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, - WGL_CONTEXT_FLAGS_ARB, GLint(flags), + /* Mask out the upper 32bits used for other flags */ + WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), #endif 0 }; @@ -157,7 +159,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G const int fallbackContextAttributes[] = { /** @todo or keep the fwcompat? */ - WGL_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), + /* Mask out the upper 32bits used for other flags */ + WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 0 }; _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); @@ -196,7 +199,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G wglDeleteContext(_context); const int fallbackContextAttributes[] = { /** @todo or keep the fwcompat? */ - WGL_CONTEXT_FLAGS_ARB, GLint(flags & ~Configuration::Flag::ForwardCompatible), + /* Mask out the upper 32bits used for other flags */ + WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), 0 }; _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); @@ -254,13 +258,11 @@ bool WindowlessWglContext::release() { return false; } -WindowlessWglContext::Configuration::Configuration(): +WindowlessWglContext::Configuration::Configuration() { #ifndef MAGNUM_TARGET_GLES - _flags{Flag::ForwardCompatible} - #else - _flags{} + addFlags(Flag::ForwardCompatible); #endif - {} +} #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments): WindowlessWglApplication{arguments, Configuration{}} {} @@ -282,7 +284,7 @@ bool WindowlessWglApplication::tryCreateContext(const Configuration& configurati CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false); WindowlessWglContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 999880de2..6bf035a4b 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -42,7 +42,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/OpenGL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Platform/Platform.h" #ifndef DOXYGEN_GENERATING_OUTPUT @@ -172,14 +172,15 @@ class WindowlessWglContext { @ref WindowlessWglApplication::createContext(), @ref WindowlessWglApplication::tryCreateContext() */ -class WindowlessWglContext::Configuration { +class WindowlessWglContext::Configuration: public GL::Context::Configuration { public: /** * @brief Context flag * + * Includes also everything from @ref GL::Context::Configuration::Flag. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ - enum class Flag: int { + enum class Flag: UnsignedLong { #ifndef MAGNUM_TARGET_GLES /** * Forward compatible context @@ -191,11 +192,30 @@ class WindowlessWglContext::Configuration { #endif /** - * Debug context. Enabled automatically if the - * `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" + * Debug context. Enabled automatically if supported by the driver + * and the @ref Flag::GpuValidation flag is set or if the + * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" * is present. */ - Debug = WGL_CONTEXT_DEBUG_BIT_ARB + Debug = WGL_CONTEXT_DEBUG_BIT_ARB, + + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) }; /** @@ -208,7 +228,9 @@ class WindowlessWglContext::Configuration { /*implicit*/ Configuration(); /** @brief Context flags */ - Flags flags() const { return _flags; } + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } /** * @brief Set context flags @@ -220,7 +242,7 @@ class WindowlessWglContext::Configuration { * @see @ref GL::Context::flags() */ Configuration& setFlags(Flags flags) { - _flags = flags; + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -233,7 +255,7 @@ class WindowlessWglContext::Configuration { * @see @ref clearFlags() */ Configuration& addFlags(Flags flags) { - _flags |= flags; + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -246,7 +268,7 @@ class WindowlessWglContext::Configuration { * @see @ref addFlags() */ Configuration& clearFlags(Flags flags) { - _flags &= ~flags; + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -274,8 +296,12 @@ class WindowlessWglContext::Configuration { */ HGLRC sharedContext() const { return _sharedContext; } + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration) + #endif + private: - Flags _flags; HGLRC _sharedContext = nullptr; }; diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 685a30892..5cb872171 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -129,7 +129,8 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co #error unsupported OpenGL ES version #endif #endif - EGL_CONTEXT_FLAGS_KHR, EGLint(flags), + /* Mask out the upper 32bits used for other flags */ + EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu), EGL_NONE }; @@ -201,7 +202,7 @@ bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration& conf CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false); WindowlessWindowsEglContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 49c28621d..80694d9b3 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -44,7 +44,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/OpenGL.h" +#include "Magnum/GL/Context.h" #include "Magnum/Platform/Platform.h" namespace Magnum { namespace Platform { @@ -158,20 +158,40 @@ class WindowlessWindowsEglContext { @ref WindowlessWindowsEglApplication::createContext(), @ref WindowlessWindowsEglApplication::tryCreateContext() */ -class WindowlessWindowsEglContext::Configuration { +class WindowlessWindowsEglContext::Configuration: public GL::Context::Configuration { public: /** * @brief Context flag * + * Includes also everything from @ref GL::Context::Configuration::Flag. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ - enum class Flag: int { + enum class Flag: UnsignedLong { /** - * Debug context. Enabled automatically if the - * `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option" + * Debug context. Enabled automatically if supported by the driver + * and the @ref Flag::GpuValidation flag is set or if the + * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" * is present. */ - Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR + Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, + + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) }; /** @@ -181,10 +201,10 @@ class WindowlessWindowsEglContext::Configuration { */ typedef Containers::EnumSet Flags; - constexpr /*implicit*/ Configuration() {} - /** @brief Context flags */ - Flags flags() const { return _flags; } + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } /** * @brief Set context flags @@ -195,7 +215,7 @@ class WindowlessWindowsEglContext::Configuration { * @see @ref GL::Context::flags() */ Configuration& setFlags(Flags flags) { - _flags = flags; + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -208,7 +228,7 @@ class WindowlessWindowsEglContext::Configuration { * @see @ref clearFlags() */ Configuration& addFlags(Flags flags) { - _flags |= flags; + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -221,7 +241,7 @@ class WindowlessWindowsEglContext::Configuration { * @see @ref addFlags() */ Configuration& clearFlags(Flags flags) { - _flags &= ~flags; + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } @@ -249,8 +269,12 @@ class WindowlessWindowsEglContext::Configuration { */ EGLContext sharedContext() const { return _sharedContext; } + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration) + #endif + private: - Flags _flags; EGLContext _sharedContext = EGL_NO_CONTEXT; }; diff --git a/src/Magnum/Platform/gl-info.cpp b/src/Magnum/Platform/gl-info.cpp index 28e205a59..4c452f5c9 100644 --- a/src/Magnum/Platform/gl-info.cpp +++ b/src/Magnum/Platform/gl-info.cpp @@ -118,7 +118,7 @@ Arguments: - `--all-extensions` --- display extensions also for fully supported versions - `--limits` --- display also limits and implementation-defined values - `--magnum-...` --- engine-specific options (see - @ref GL-Context-command-line for details) + @ref GL-Context-usage-command-line for details) @subsection magnum-gl-info-usage-emscripten Usage on Emscripten diff --git a/src/Magnum/Text/fontconverter.cpp b/src/Magnum/Text/fontconverter.cpp index 347578216..9ef08563c 100644 --- a/src/Magnum/Text/fontconverter.cpp +++ b/src/Magnum/Text/fontconverter.cpp @@ -103,7 +103,7 @@ Arguments: field computation will not be used. (default: `"256 256"`) - `--radius N` --- distance field computation radius (default: `24`) - `--magnum-...` --- engine-specific options (see - @ref GL-Context-command-line for details) + @ref GL-Context-usage-command-line for details) The resulting font files can be then used as specified in the documentation of `converter` plugin. diff --git a/src/Magnum/TextureTools/distancefieldconverter.cpp b/src/Magnum/TextureTools/distancefieldconverter.cpp index d5c81a3cc..087b93988 100644 --- a/src/Magnum/TextureTools/distancefieldconverter.cpp +++ b/src/Magnum/TextureTools/distancefieldconverter.cpp @@ -108,7 +108,7 @@ Arguments: - `--output-size "X Y"` --- size of output image - `--radius N` --- distance field computation radius - `--magnum-...` --- engine-specific options (see - @ref GL-Context-command-line for details) + @ref GL-Context-usage-command-line for details) Images with @ref PixelFormat::R8Unorm, @ref PixelFormat::RGB8Unorm or @ref PixelFormat::RGBA8Unorm are accepted on input. From 81a3ae5d447aad38ea16f12f2c5bcb07d5292508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 21:41:08 +0100 Subject: [PATCH 023/161] GL: this doesn't need to be exported. --- src/Magnum/GL/Context.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index c26e72455..8a1766a74 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -821,7 +821,7 @@ class MAGNUM_GL_EXPORT Context { friend Implementation::ContextState; #endif - void disableDriverWorkaround(Containers::StringView workaround); + MAGNUM_GL_LOCAL void disableDriverWorkaround(Containers::StringView workaround); /* Defined in Implementation/driverSpecific.cpp */ MAGNUM_GL_LOCAL void setupDriverWorkarounds(); From bc9a34ce1be36f987d60a28625b03bef319ae0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 21:42:59 +0100 Subject: [PATCH 024/161] GL: no need for these hacks anymore. --- src/Magnum/GL/Test/ContextGLTest.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Magnum/GL/Test/ContextGLTest.cpp b/src/Magnum/GL/Test/ContextGLTest.cpp index d14910ca6..e0c795249 100644 --- a/src/Magnum/GL/Test/ContextGLTest.cpp +++ b/src/Magnum/GL/Test/ContextGLTest.cpp @@ -246,8 +246,9 @@ void ContextGLTest::makeCurrent() { CORRADE_VERIFY(!Context::hasCurrent()); { - const char* argv[]{"", "--magnum-log", "off"}; - Platform::GLContext ctx{Int(Containers::arraySize(argv)), argv}; + Platform::GLContext ctx{Context::Configuration{} + .setFlags(Context::Configuration::Flag::QuietLog) + }; CORRADE_VERIFY(Context::hasCurrent()); } From 5803d52a86cc621ae8b96f43e6ee4f5473917b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 21:41:57 +0100 Subject: [PATCH 025/161] Platform: minor cleanup. --- src/Magnum/Platform/WindowlessEglApplication.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 1eb1154b3..9fca277c9 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -578,7 +578,9 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati Configuration mergedConfiguration{configuration}; #ifndef MAGNUM_TARGET_WEBGL if(!mergedConfiguration.device()) - mergedConfiguration.setDevice(_commandLineDevice).setCudaDevice(_commandLineCudaDevice); + mergedConfiguration + .setDevice(_commandLineDevice) + .setCudaDevice(_commandLineCudaDevice); #endif WindowlessEglContext glContext{mergedConfiguration, _context.get()}; From 24d70937d7b80b4d5be687f68c79b4c55383bc90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 21:42:11 +0100 Subject: [PATCH 026/161] Platform: this include isn't needed. --- src/Magnum/Platform/GLContext.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Platform/GLContext.h b/src/Magnum/Platform/GLContext.h index dd372478e..5a0c5aa7a 100644 --- a/src/Magnum/Platform/GLContext.h +++ b/src/Magnum/Platform/GLContext.h @@ -31,7 +31,7 @@ */ #endif -#include +#include #include "Magnum/configure.h" From e512afa31e3f4aba8260d1631d35e89a6ecbfb3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 21:43:21 +0100 Subject: [PATCH 027/161] Platform: this comment makes no sense here anymore. The GL-related stuff was moved to GLConfiguration *long* ago. --- src/Magnum/Platform/AndroidApplication.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index e09a2e368..bcc28757d 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -529,7 +529,6 @@ class AndroidApplication::GLConfiguration: public GL::Context::Configuration { /** @brief Configuration -Double-buffered RGBA canvas with depth and stencil buffers. @see @ref AndroidApplication(), @ref GLConfiguration, @ref create(), @ref tryCreate() */ From 6cc57246a559e51772cceb13fe3a68ff61840822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 22:05:06 +0100 Subject: [PATCH 028/161] GL: whoops. Broken since 0ceb54ed7df24ec1a79727397d3afe5cfd94142e, but the two code paths actually differ only by an enum name so it didn't cause any crashes. (I wonder why I need two different code paths at all.) --- src/Magnum/GL/Implementation/TextureState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index aca81d760..9e6e08659 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -428,7 +428,7 @@ TextureState::TextureState(Context& context, Containers::StaticArrayView()) { + if(context.isExtensionSupported()) { extensions[Extensions::ARB::texture_filter_anisotropic::Index] = Extensions::ARB::texture_filter_anisotropic::string(); From 8b95542497cba2b3875da9ed4f3dfe98988abbdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 22:12:03 +0100 Subject: [PATCH 029/161] GL: we don't need two code paths that do effectively the same. The enum value is exactly the same for both. --- src/Magnum/GL/AbstractTexture.cpp | 8 +------- src/Magnum/GL/AbstractTexture.h | 5 +---- src/Magnum/GL/Implementation/TextureState.cpp | 4 ++-- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/Magnum/GL/AbstractTexture.cpp b/src/Magnum/GL/AbstractTexture.cpp index 24fc8f128..29cdd3dd9 100644 --- a/src/Magnum/GL/AbstractTexture.cpp +++ b/src/Magnum/GL/AbstractTexture.cpp @@ -1280,13 +1280,7 @@ void AbstractTexture::parameterIImplementationDSA(const GLenum parameter, const void AbstractTexture::setMaxAnisotropyImplementationNoOp(GLfloat) {} -#ifndef MAGNUM_TARGET_GLES -void AbstractTexture::setMaxAnisotropyImplementationArb(GLfloat anisotropy) { - (this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_MAX_ANISOTROPY, anisotropy); -} -#endif - -void AbstractTexture::setMaxAnisotropyImplementationExt(GLfloat anisotropy) { +void AbstractTexture::setMaxAnisotropyImplementationArbOrExt(GLfloat anisotropy) { (this->*Context::current().state().texture->parameterfImplementation)( #ifndef MAGNUM_TARGET_GLES GL_TEXTURE_MAX_ANISOTROPY diff --git a/src/Magnum/GL/AbstractTexture.h b/src/Magnum/GL/AbstractTexture.h index bface20b9..87027a8f2 100644 --- a/src/Magnum/GL/AbstractTexture.h +++ b/src/Magnum/GL/AbstractTexture.h @@ -586,10 +586,7 @@ class MAGNUM_GL_EXPORT AbstractTexture: public AbstractObject { #endif void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationNoOp(GLfloat); - #ifndef MAGNUM_TARGET_GLES - void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationArb(GLfloat anisotropy); - #endif - void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationExt(GLfloat anisotropy); + void MAGNUM_GL_LOCAL setMaxAnisotropyImplementationArbOrExt(GLfloat anisotropy); #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void MAGNUM_GL_LOCAL getLevelParameterImplementationDefault(GLint level, GLenum parameter, GLint* values); diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index 9e6e08659..0717b679e 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -432,14 +432,14 @@ TextureState::TextureState(Context& context, Containers::StaticArrayView()) { extensions[Extensions::EXT::texture_filter_anisotropic::Index] = Extensions::EXT::texture_filter_anisotropic::string(); - setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationExt; + setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationArbOrExt; } else setMaxAnisotropyImplementation = &AbstractTexture::setMaxAnisotropyImplementationNoOp; #ifndef MAGNUM_TARGET_GLES From 8028cbe633372ee91ec7d1d0b910884cecc8e4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 22:09:12 +0100 Subject: [PATCH 030/161] GL: ensure no errors are thrown when asking for Context strings. 'cuz I have a feelink like they do get thrown. --- src/Magnum/GL/Test/ContextGLTest.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Magnum/GL/Test/ContextGLTest.cpp b/src/Magnum/GL/Test/ContextGLTest.cpp index e0c795249..362ec5970 100644 --- a/src/Magnum/GL/Test/ContextGLTest.cpp +++ b/src/Magnum/GL/Test/ContextGLTest.cpp @@ -198,6 +198,9 @@ void ContextGLTest::stringFlags() { TestSuite::Compare::GreaterOrEqual); } } + + /* There should be no errors caused by any of these */ + MAGNUM_VERIFY_NO_GL_ERROR(); } void ContextGLTest::constructConfiguration() { From deddda418e4003f79bf292baea1ea4d0a731e58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 23:06:42 +0100 Subject: [PATCH 031/161] GL: deprecate Context::supportedExtensions(). I don't see a real use case for this API (and don't remember ever using it) and it only causes extra overhead during context creation (and then a ton of useless allocations at runtime). --- src/Magnum/GL/Context.cpp | 4 ++++ src/Magnum/GL/Context.h | 11 +++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 2fe912ccc..d86aa5b35 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -738,7 +738,9 @@ Context::Context(Context&& other) noexcept: _version{other._version}, #endif _extensionStatus{other._extensionStatus}, _extensionRequiredVersion{other._extensionRequiredVersion}, + #ifdef MAGNUM_BUILD_DEPRECATED _supportedExtensions{std::move(other._supportedExtensions)}, + #endif _state{std::move(other._state)}, _detectedDrivers{std::move(other._detectedDrivers)} { @@ -909,7 +911,9 @@ bool Context::tryCreate(const Configuration& configuration) { const Containers::Array extensions = extensionStrings(); for(const Containers::StringView extension: extensions) { if(const Extension* found = findExtension(extension, future)) { + #ifdef MAGNUM_BUILD_DEPRECATED arrayAppend(_supportedExtensions, *found); + #endif _extensionStatus.set(found->index(), true); } } diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 8a1766a74..e0d9fdb3e 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -615,16 +615,21 @@ class MAGNUM_GL_EXPORT Context { Flags flags() const { return _flags; } #endif + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Supported extensions * * The list contains only extensions from OpenGL versions newer than * the current. - * @see @ref isExtensionSupported(), @ref Extension::extensions() + * @m_deprecated_since_latest Deprecated as it doesn't provide anything + * that @ref extensionStrings(), @ref Extension::extensions() and + * @ref isExtensionSupported() wouldn't provide already and only + * causes extra overhead during context creation. */ - Containers::ArrayView supportedExtensions() const { + CORRADE_DEPRECATED("use extensionStrings(), Extension::extensions() and isExtensionSupported() instead") Containers::ArrayView supportedExtensions() const { return _supportedExtensions; } + #endif #ifndef MAGNUM_TARGET_GLES /** @@ -842,7 +847,9 @@ class MAGNUM_GL_EXPORT Context { this field contains the minimal required GL version the extension needs. Extensions that are disabled have None here. */ Containers::StaticArray _extensionRequiredVersion; + #ifdef MAGNUM_BUILD_DEPRECATED Containers::Array _supportedExtensions; + #endif Containers::Pointer _state; From dec3d74d8a45c0e972b44cd1aa88ff3decc6e841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Feb 2021 22:54:33 +0100 Subject: [PATCH 032/161] GL: MSVC 2015, don't die yet. --- src/Magnum/GL/Context.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index d86aa5b35..f1ad5c139 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -533,7 +533,13 @@ constexpr Extension ExtensionListES320[]{ }; #endif -constexpr struct { +#ifdef CORRADE_MSVC2015_COMPATIBILITY +/* MSVC 2015 ICEs in the loop below if this is constexpr. Don't, then. */ +const +#else +constexpr +#endif +struct { Version version; Containers::ArrayView extensions; } KnownExtensionsForVersion[]{ From 5714828e0a38941fdf8e4ab2da71a7398ea2e2be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 25 Feb 2021 11:37:43 +0100 Subject: [PATCH 033/161] GL: the compiler outsmarted me and made my test fail. --- src/Magnum/GL/Test/ContextTest.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Magnum/GL/Test/ContextTest.cpp b/src/Magnum/GL/Test/ContextTest.cpp index 0651a2a31..49b00ff6c 100644 --- a/src/Magnum/GL/Test/ContextTest.cpp +++ b/src/Magnum/GL/Test/ContextTest.cpp @@ -36,6 +36,8 @@ namespace Magnum { namespace GL { namespace Test { namespace { +using namespace Containers::Literals; + struct ContextTest: TestSuite::Tester { explicit ContextTest(); @@ -141,20 +143,24 @@ void ContextTest::isExtension() { } void ContextTest::configurationConstruct() { + /* In order to verify the string literals get properly interned I could + make them non-global (by converting from const char*) and then test that + they are global and with a different pointer. However, compilers are + clever and on static builds they could just deduplicate the literals, + which would cause this test to fail. Instead I make them + non-null-terminated which blocks the compiler from combining them + together. */ #ifndef MAGNUM_TARGET_GLES - const Containers::StringView a = "no-layout-qualifiers-on-old-glsl"; - const Containers::StringView b = "nv-compressed-block-size-in-bits"; - const Containers::StringView c = "nv-cubemap-inconsistent-compressed-image-size"; + const Containers::StringView a = "no-layout-qualifiers-on-old-glsl!"_s.except(1); + const Containers::StringView b = "nv-compressed-block-size-in-bits!"_s.except(1); + const Containers::StringView c = "nv-cubemap-inconsistent-compressed-image-size!"_s.except(1); #elif !defined(MAGNUM_TARGET_WEBGL) - const Containers::StringView a = "swiftshader-no-empty-egl-context-flags"; - const Containers::StringView b = "swiftshader-egl-context-needs-pbuffer"; - const Containers::StringView c = "angle-chatty-shader-compiler"; + const Containers::StringView a = "swiftshader-no-empty-egl-context-flags!"_s.except(1); + const Containers::StringView b = "swiftshader-egl-context-needs-pbuffer!"_s.except(1); + const Containers::StringView c = "angle-chatty-shader-compiler!"_s.except(1); #else /* No general WebGL workarounds to test */ #endif - /* Deliberately not having the literals global to test that they get - converted to something else */ - CORRADE_VERIFY(!(a.flags() & Containers::StringViewFlag::Global)); Context::Configuration configuration; configuration From 46d8f2536307b26d84589081994b0df7cc64a8a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 25 Feb 2021 11:38:07 +0100 Subject: [PATCH 034/161] external: don't define WIN32_LEAN_AND_MEAN just for shits and giggles. We're not including windows.h there (fortunately!), so there's no point in defining such a macro. Also the proper way would be defining it only if it's not already defined to avoid macro redefinition warnings. --- src/MagnumExternal/OpenGL/GL/flextGL.h | 1 - src/MagnumExternal/OpenGL/GL/flextGL.h.template | 1 - src/MagnumExternal/OpenGL/GLES2/flextGL.h | 1 - src/MagnumExternal/OpenGL/GLES2/flextGL.h.template | 1 - src/MagnumExternal/OpenGL/GLES3/flextGL.h | 1 - src/MagnumExternal/OpenGL/GLES3/flextGL.h.template | 1 - 6 files changed, 6 deletions(-) diff --git a/src/MagnumExternal/OpenGL/GL/flextGL.h b/src/MagnumExternal/OpenGL/GL/flextGL.h index 256b80ca9..e3fa1ee3e 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGL.h +++ b/src/MagnumExternal/OpenGL/GL/flextGL.h @@ -80,7 +80,6 @@ void flextGLInit(Magnum::GL::Context& context); #endif #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -#define WIN32_LEAN_AND_MEAN 1 #ifndef WINAPI #define WINAPI __stdcall #endif diff --git a/src/MagnumExternal/OpenGL/GL/flextGL.h.template b/src/MagnumExternal/OpenGL/GL/flextGL.h.template index 71cd158ea..69c22f1c0 100644 --- a/src/MagnumExternal/OpenGL/GL/flextGL.h.template +++ b/src/MagnumExternal/OpenGL/GL/flextGL.h.template @@ -81,7 +81,6 @@ void flextGLInit(Magnum::GL::Context& context); #endif #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -#define WIN32_LEAN_AND_MEAN 1 #ifndef WINAPI #define WINAPI __stdcall #endif diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGL.h b/src/MagnumExternal/OpenGL/GLES2/flextGL.h index 2bce54cde..851e58f37 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGL.h +++ b/src/MagnumExternal/OpenGL/GLES2/flextGL.h @@ -67,7 +67,6 @@ void flextGLInit(Magnum::GL::Context& context); #endif #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -#define WIN32_LEAN_AND_MEAN 1 #ifndef WINAPI #define WINAPI __stdcall #endif diff --git a/src/MagnumExternal/OpenGL/GLES2/flextGL.h.template b/src/MagnumExternal/OpenGL/GLES2/flextGL.h.template index 510c65a55..ed45a2949 100644 --- a/src/MagnumExternal/OpenGL/GLES2/flextGL.h.template +++ b/src/MagnumExternal/OpenGL/GLES2/flextGL.h.template @@ -68,7 +68,6 @@ void flextGLInit(Magnum::GL::Context& context); #endif #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -#define WIN32_LEAN_AND_MEAN 1 #ifndef WINAPI #define WINAPI __stdcall #endif diff --git a/src/MagnumExternal/OpenGL/GLES3/flextGL.h b/src/MagnumExternal/OpenGL/GLES3/flextGL.h index 86428b761..360803fee 100644 --- a/src/MagnumExternal/OpenGL/GLES3/flextGL.h +++ b/src/MagnumExternal/OpenGL/GLES3/flextGL.h @@ -72,7 +72,6 @@ void flextGLInit(Magnum::GL::Context& context); #endif #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -#define WIN32_LEAN_AND_MEAN 1 #ifndef WINAPI #define WINAPI __stdcall #endif diff --git a/src/MagnumExternal/OpenGL/GLES3/flextGL.h.template b/src/MagnumExternal/OpenGL/GLES3/flextGL.h.template index d090bdd6d..e94ecd681 100644 --- a/src/MagnumExternal/OpenGL/GLES3/flextGL.h.template +++ b/src/MagnumExternal/OpenGL/GLES3/flextGL.h.template @@ -73,7 +73,6 @@ void flextGLInit(Magnum::GL::Context& context); #endif #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) -#define WIN32_LEAN_AND_MEAN 1 #ifndef WINAPI #define WINAPI __stdcall #endif From 4de9f75e1c1031ff1b43a887aa6d9dcba2ab6dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 25 Feb 2021 12:37:36 +0100 Subject: [PATCH 035/161] GL: make the Context::makeCurrent() test more robust. So if it fails somewhere, the current context is reset back. --- src/Magnum/GL/Test/ContextGLTest.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Magnum/GL/Test/ContextGLTest.cpp b/src/Magnum/GL/Test/ContextGLTest.cpp index 362ec5970..f6c7df05c 100644 --- a/src/Magnum/GL/Test/ContextGLTest.cpp +++ b/src/Magnum/GL/Test/ContextGLTest.cpp @@ -242,26 +242,27 @@ void ContextGLTest::constructConfiguration() { void ContextGLTest::makeCurrent() { CORRADE_VERIFY(Context::hasCurrent()); - - Context& current = Context::current(); - Context::makeCurrent(nullptr); - - CORRADE_VERIFY(!Context::hasCurrent()); + Context* current = &Context::current(); { - Platform::GLContext ctx{Context::Configuration{} - .setFlags(Context::Configuration::Flag::QuietLog) - }; + Context::makeCurrent(nullptr); + Containers::ScopeGuard resetCurrent{current, Context::makeCurrent}; - CORRADE_VERIFY(Context::hasCurrent()); - } + CORRADE_VERIFY(!Context::hasCurrent()); - CORRADE_VERIFY(!Context::hasCurrent()); + { + Platform::GLContext ctx{Context::Configuration{} + .setFlags(Context::Configuration::Flag::QuietLog) + }; - Context::makeCurrent(¤t); + CORRADE_VERIFY(Context::hasCurrent()); + } + + CORRADE_VERIFY(!Context::hasCurrent()); + } CORRADE_VERIFY(Context::hasCurrent()); - CORRADE_COMPARE(&Context::current(), ¤t); + CORRADE_COMPARE(&Context::current(), current); } #ifndef CORRADE_TARGET_EMSCRIPTEN From 7111085d1e9a9accc29bc1c4b97346a51d57b8bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 25 Feb 2021 15:59:25 +0100 Subject: [PATCH 036/161] GL: add an extensive test for Context moving. FAILS! Because the move constructor implementation moves not even a half of the members. Silly. --- src/Magnum/GL/Test/ContextGLTest.cpp | 147 +++++++++++++++++++++++++++ src/Magnum/GL/Test/ContextTest.cpp | 12 +-- 2 files changed, 150 insertions(+), 9 deletions(-) diff --git a/src/Magnum/GL/Test/ContextGLTest.cpp b/src/Magnum/GL/Test/ContextGLTest.cpp index f6c7df05c..5dfd5edd5 100644 --- a/src/Magnum/GL/Test/ContextGLTest.cpp +++ b/src/Magnum/GL/Test/ContextGLTest.cpp @@ -48,6 +48,8 @@ struct ContextGLTest: OpenGLTester { void constructConfiguration(); + void constructMove(); + void makeCurrent(); #ifndef CORRADE_TARGET_EMSCRIPTEN @@ -139,12 +141,55 @@ struct { "Disabling extensions:\n GL_EXT_texture_filter_anisotropic\n", {}}, }; +struct { + const char* name; + Context::Configuration::Flags flags; + Containers::Array disabledWorkarounds; + Containers::Array disabledExtensions; + bool workaroundDisabled, extensionDisabled; + Containers::Array args; + Containers::StringView logShouldContain, logShouldNotContain; +} ConstructMoveData[] { + {"default log", {}, {}, {}, false, false, {}, + "Renderer: ", {}}, + {"quiet log", + Context::Configuration::Flag::QuietLog, + {}, {}, false, false, {}, + {}, "Renderer: "}, + {"quiet log on command line", {}, {}, {}, false, false, + Containers::array({"", "--magnum-log", "quiet"}), + {}, "Renderer: "}, + {"disabled extension", {}, {}, + Containers::array({Extensions::EXT::texture_filter_anisotropic{}}), + false, true, {}, + "Disabling extensions:\n GL_EXT_texture_filter_anisotropic\n", {}}, + {"disabled extension on command line", {}, {}, {}, + false, true, + Containers::array({"", "--magnum-disable-extensions", "GL_EXT_texture_filter_anisotropic"}), + "Disabling extensions:\n GL_EXT_texture_filter_anisotropic\n", {}}, + #ifndef MAGNUM_TARGET_GLES + {"disabled workaround", {}, + Containers::array({"no-layout-qualifiers-on-old-glsl"_s}), + {}, + true, false, + {}, + {}, "no-layout-qualifiers-on-old-glsl"}, + {"disabled workaround on command line", {}, {}, {}, + true, false, + Containers::array({"", "--magnum-disable-workarounds", "no-layout-qualifiers-on-old-glsl"}), + {}, "no-layout-qualifiers-on-old-glsl"}, + #endif +}; + ContextGLTest::ContextGLTest() { addTests({&ContextGLTest::stringFlags}); addInstancedTests({&ContextGLTest::constructConfiguration}, Containers::arraySize(ConstructConfigurationData)); + addInstancedTests({&ContextGLTest::constructMove}, + Containers::arraySize(ConstructMoveData)); + addTests({ &ContextGLTest::makeCurrent, @@ -240,6 +285,108 @@ void ContextGLTest::constructConfiguration() { CORRADE_VERIFY(!Containers::StringView{out.str()}.contains(data.logShouldNotContain)); } +void ContextGLTest::constructMove() { + auto&& data = ConstructMoveData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + if(std::getenv("MAGNUM_DISABLE_WORKAROUNDS")) + CORRADE_SKIP("Can't test with the MAGNUM_DISABLE_WORKAROUNDS environment variable set"); + if(std::getenv("MAGNUM_DISABLE_EXTENSIONS")) + CORRADE_SKIP("Can't test with the MAGNUM_DISABLE_EXTENSIONS environment variable set"); + + CORRADE_VERIFY(Context::hasCurrent()); + + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::EXT::texture_filter_anisotropic::string() + std::string{" is not supported, skipping"}); + + Context* current = &Context::current(); + Context::makeCurrent(nullptr); + Containers::ScopeGuard resetCurrent{current, Context::makeCurrent}; + + /* First gather just the command-line parameters. Nothing to verify here as + it's not initialized yet. */ + Platform::GLContext a{NoCreate, Int(data.args.size()), data.args}; + + /* The context is not created yet, so it doesn't set it as current yet */ + CORRADE_VERIFY(!Context::hasCurrent()); + + #ifndef MAGNUM_TARGET_GLES + /* This function pointer should get populated by create() if the function + loader gets moved correctly */ + glGenBuffers = nullptr; + #endif + + /* Move and create. This should take into account all parameters passed + from above and combine them with what arrived through Configuration. */ + Platform::GLContext b = std::move(a); + + /* The context is still not created here either */ + CORRADE_VERIFY(!Context::hasCurrent()); + + std::ostringstream out; + { + Debug redirectOut{&out}; + b.create(Context::Configuration{} + .setFlags(data.flags) + #ifndef MAGNUM_TARGET_GLES + .addDisabledWorkarounds(data.disabledWorkarounds) + #endif + .addDisabledExtensions(data.disabledExtensions)); + } + /** @todo TestSuite::Compare::StringContains / NotContains for proper diag */ + if(!data.logShouldContain.isEmpty()) + CORRADE_VERIFY(Containers::StringView{out.str()}.contains(data.logShouldContain)); + if(!data.logShouldNotContain.isEmpty()) + CORRADE_VERIFY(!Containers::StringView{out.str()}.contains(data.logShouldNotContain)); + + /* The context is created now */ + CORRADE_VERIFY(Context::hasCurrent()); + CORRADE_COMPARE(&Context::current(), &b); + + #ifndef MAGNUM_TARGET_GLES + /* The function pointer got populated */ + CORRADE_VERIFY(glGenBuffers); + #endif + + #ifndef MAGNUM_TARGET_GLES + /* This is an internal undocumented API but shh */ + CORRADE_COMPARE(b.isDriverWorkaroundDisabled("no-layout-qualifiers-on-old-glsl"), data.workaroundDisabled); + #endif + CORRADE_COMPARE(b.isExtensionSupported(), !data.extensionDisabled); + CORRADE_COMPARE(b.isExtensionDisabled(), data.extensionDisabled); + const Version version = b.version(); + CORRADE_VERIFY(UnsignedInt(version)); + #ifndef MAGNUM_TARGET_WEBGL + const Context::Flags flags = b.flags(); + #endif + const Context::DetectedDrivers detectedDriver = b.detectedDriver(); + const Implementation::State* state = &b.state(); + + /* Now move the created context and verify the remaining state gets + transferred as well */ + Platform::GLContext c = std::move(b); + #ifndef MAGNUM_TARGET_GLES + /* This is an internal undocumented API but shh */ + CORRADE_COMPARE(c.isDriverWorkaroundDisabled("no-layout-qualifiers-on-old-glsl"), data.workaroundDisabled); + #endif + CORRADE_COMPARE(c.isExtensionSupported(), !data.extensionDisabled); + CORRADE_COMPARE(c.isExtensionDisabled(), data.extensionDisabled); + CORRADE_COMPARE(c.version(), version); + #ifndef MAGNUM_TARGET_WEBGL + CORRADE_COMPARE(c.flags(), flags); + #endif + CORRADE_COMPARE(c.detectedDriver(), detectedDriver); + CORRADE_COMPARE(&c.state(), state); + + /* The current context pointer is transferred to the moved-to instance */ + CORRADE_VERIFY(Context::hasCurrent()); + CORRADE_COMPARE(&Context::current(), &c); + + /* Only move-construction allowed */ + CORRADE_VERIFY(!std::is_move_assignable{}); + CORRADE_VERIFY(std::is_nothrow_move_constructible::value); +} + void ContextGLTest::makeCurrent() { CORRADE_VERIFY(Context::hasCurrent()); Context* current = &Context::current(); diff --git a/src/Magnum/GL/Test/ContextTest.cpp b/src/Magnum/GL/Test/ContextTest.cpp index 49b00ff6c..01fb41a4e 100644 --- a/src/Magnum/GL/Test/ContextTest.cpp +++ b/src/Magnum/GL/Test/ContextTest.cpp @@ -49,7 +49,7 @@ struct ContextTest: TestSuite::Tester { void configurationConstructMove(); void constructNoCreate(); - void constructCopyMove(); + void constructCopy(); void makeCurrentNoOp(); @@ -71,7 +71,7 @@ ContextTest::ContextTest() { &ContextTest::configurationConstructMove, &ContextTest::constructNoCreate, - &ContextTest::constructCopyMove, + &ContextTest::constructCopy, &ContextTest::makeCurrentNoOp, @@ -353,15 +353,9 @@ void ContextTest::constructNoCreate() { CORRADE_VERIFY(!(std::is_convertible::value)); } -void ContextTest::constructCopyMove() { - /* Only move-construction allowed */ +void ContextTest::constructCopy() { CORRADE_VERIFY(!std::is_copy_constructible{}); - CORRADE_VERIFY(std::is_move_constructible{}); CORRADE_VERIFY(!std::is_copy_assignable{}); - CORRADE_VERIFY(!std::is_move_assignable{}); - - CORRADE_VERIFY(std::is_nothrow_move_constructible::value); - /* No move assignment */ } void ContextTest::makeCurrentNoOp() { From 32018051f2eb86a47f5d4eca669fcac1c84da0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 25 Feb 2021 16:08:59 +0100 Subject: [PATCH 037/161] GL: fix Context move constructor. The missing pieces made the delayed creation broken, it worked properly when the context was created *and then* moved. --- doc/changelog.dox | 3 ++- src/Magnum/GL/Context.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index ef79ad9d2..5f0558dec 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -295,7 +295,8 @@ See also: @subsection changelog-latest-bugfixes Bug fixes - @ref GL::Context move constructor was not marked @cpp noexcept @ce by - accident + accident and it was also not really moving everything properly, especially + when delayed creation was done on the moved-to object - @ref GL::Renderer::MemoryBarrier::ShaderStorage had an incorrect value - Fixed assertions related to OpenGL driver workarounds when the proprietary AMDGPU PRO drivers are used on Linux diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index f1ad5c139..4e1239b05 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -738,7 +738,9 @@ Context::Context(NoCreateT, Utility::Arguments& args, Int argc, const char** arg } } -Context::Context(Context&& other) noexcept: _version{other._version}, +Context::Context(Context&& other) noexcept: + _functionLoader{other._functionLoader}, + _version{other._version}, #ifndef MAGNUM_TARGET_WEBGL _flags{other._flags}, #endif @@ -748,7 +750,10 @@ Context::Context(Context&& other) noexcept: _version{other._version}, _supportedExtensions{std::move(other._supportedExtensions)}, #endif _state{std::move(other._state)}, - _detectedDrivers{std::move(other._detectedDrivers)} + _detectedDrivers{std::move(other._detectedDrivers)}, + _driverWorkarounds{std::move(other._driverWorkarounds)}, + _disabledExtensions{std::move(other._disabledExtensions)}, + _internalFlags{other._internalFlags} { if(currentContext == &other) currentContext = this; } From b29de865af8e9d7511d42010af2f96e0770b0ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 25 Feb 2021 16:57:14 +0100 Subject: [PATCH 038/161] GL: no need for separate Context::InternalFlags anymore. The public Context::Configuration::Flags can supplement that, and that also makes option merging easier. --- src/Magnum/GL/Context.cpp | 26 ++++++------ src/Magnum/GL/Context.h | 40 ++++++++++++------- src/Magnum/Platform/GlfwApplication.cpp | 2 +- src/Magnum/Platform/Sdl2Application.cpp | 2 +- .../Platform/WindowlessEglApplication.cpp | 12 +++--- .../Platform/WindowlessGlxApplication.cpp | 2 +- .../Platform/WindowlessWglApplication.cpp | 2 +- .../WindowlessWindowsEglApplication.cpp | 2 +- 8 files changed, 50 insertions(+), 38 deletions(-) diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 4e1239b05..e1b2cb0ca 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -703,13 +703,13 @@ Context::Context(NoCreateT, Utility::Arguments& args, Int argc, const char** arg /* Decide how to display initialization log */ if(args.value("log") == "verbose" || args.value("log") == "VERBOSE") - _internalFlags |= InternalFlag::DisplayVerboseInitializationLog; - else if(!(args.value("log") == "quiet" || args.value("log") == "QUIET")) - _internalFlags |= InternalFlag::DisplayInitializationLog; + _configurationFlags |= Configuration::Flag::VerboseLog; + else if(args.value("log") == "quiet" || args.value("log") == "QUIET") + _configurationFlags |= Configuration::Flag::QuietLog; /* Decide whether to enable GPU validation */ if(args.value("gpu-validation") == "on" || args.value("gpu-validation") == "ON") - _internalFlags |= InternalFlag::GpuValidation; + _configurationFlags |= Configuration::Flag::GpuValidation; /* If there are any disabled workarounds, save them until tryCreate() uses them. The disableWorkaround() function saves the internal string view @@ -753,7 +753,7 @@ Context::Context(Context&& other) noexcept: _detectedDrivers{std::move(other._detectedDrivers)}, _driverWorkarounds{std::move(other._driverWorkarounds)}, _disabledExtensions{std::move(other._disabledExtensions)}, - _internalFlags{other._internalFlags} + _configurationFlags{other._configurationFlags} { if(currentContext == &other) currentContext = this; } @@ -776,14 +776,14 @@ bool Context::tryCreate(const Configuration& configuration) { quiet, it'll override the verbose setting from the configuration; if it says verbose, the quiet setting from the configuration will be ignored */ - if((configuration.flags() & Configuration::Flag::VerboseLog) && (_internalFlags & InternalFlag::DisplayInitializationLog)) - _internalFlags |= InternalFlag::DisplayVerboseInitializationLog; - else if((configuration.flags() & Configuration::Flag::QuietLog) && !(_internalFlags >= InternalFlag::DisplayVerboseInitializationLog)) - _internalFlags &= ~InternalFlag::DisplayInitializationLog; + if((configuration.flags() & Configuration::Flag::VerboseLog) && !(_configurationFlags & Configuration::Flag::QuietLog)) + _configurationFlags |= Configuration::Flag::VerboseLog; + else if((configuration.flags() & Configuration::Flag::QuietLog) && !(_configurationFlags & Configuration::Flag::VerboseLog)) + _configurationFlags |= Configuration::Flag::QuietLog; /* GPU validation is enabled if either enables it */ if(configuration.flags() & Configuration::Flag::GpuValidation) - _internalFlags |= InternalFlag::GpuValidation; + _configurationFlags |= Configuration::Flag::GpuValidation; /* Driver workarounds get merged. Not using disableDriverWorkaround() here since the Configuration already contains the internal string views. */ @@ -946,7 +946,7 @@ bool Context::tryCreate(const Configuration& configuration) { currentContext = this; /* Decide whether to print the initialization output or not */ - std::ostream* output = _internalFlags & InternalFlag::DisplayInitializationLog ? Debug::output() : nullptr; + std::ostream* output = _configurationFlags & Configuration::Flag::QuietLog ? nullptr : Debug::output(); /* Print some info and initialize state tracker (which also prints some more info). Mesa's renderer string has a space at the end, trim that. */ @@ -978,7 +978,7 @@ bool Context::tryCreate(const Configuration& configuration) { Renderer::initializeContextBasedFunctionality(); /* Enable GPU validation, if requested */ - if(_internalFlags & InternalFlag::GpuValidation) { + if(_configurationFlags & Configuration::Flag::GpuValidation) { #ifndef MAGNUM_TARGET_WEBGL if(isExtensionSupported()) { Renderer::enable(Renderer::Feature::DebugOutput); @@ -987,7 +987,7 @@ bool Context::tryCreate(const Configuration& configuration) { if((detectedDriver() & DetectedDriver::Amd) && !(flags() & Flag::Debug)) { Warning{} << "GL::Context: GPU validation on AMD drivers requires debug context to work properly"; - } else if(_internalFlags >= InternalFlag::DisplayVerboseInitializationLog) { + } else if(_configurationFlags & Configuration::Flag::VerboseLog) { Debug{} << "GL::Context: enabling GPU validation"; } diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index e0d9fdb3e..3da9fcdf2 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -65,6 +65,17 @@ namespace Implementation { /** @todo C++17: use &&... instead of all this */ public: enum: bool { value = IsExtension::value && IsExtension::value }; }; + + /* Context::Configuration::Flag, but because we need to use it inside + Context before the Configuration class is defined, it has to be here */ + enum class ContextConfigurationFlag: UnsignedLong { + /* Keeping the 32-bit range reserved for actual GL context flags */ + QuietLog = 1ull << 61, + VerboseLog = 1ull << 62, + GpuValidation = 1ull << 63 + }; + typedef Containers::EnumSet ContextConfigurationFlags; + CORRADE_ENUMSET_OPERATORS(ContextConfigurationFlags) } /** @@ -789,15 +800,6 @@ class MAGNUM_GL_EXPORT Context { #ifdef DOXYGEN_GENERATING_OUTPUT private: #endif - /* Applications want an easy way to know if GPU validation is enabled */ - enum class InternalFlag: UnsignedByte { - DisplayInitializationLog = 1 << 0, - DisplayVerboseInitializationLog = DisplayInitializationLog|(1 << 1), - GpuValidation = 1 << 2 - }; - typedef Containers::EnumSet InternalFlags; - CORRADE_ENUMSET_FRIEND_OPERATORS(InternalFlags) - bool isDriverWorkaroundDisabled(Containers::StringView workaround); Implementation::State& state() { return *_state; } @@ -805,7 +807,7 @@ class MAGNUM_GL_EXPORT Context { state() pointer is not ready yet so we have to pass it directly */ MAGNUM_GL_LOCAL bool isCoreProfileInternal(Implementation::ContextState& state); - InternalFlags internalFlags() const { return _internalFlags; } + Implementation::ContextConfigurationFlags configurationFlags() const { return _configurationFlags; } #ifdef DOXYGEN_GENERATING_OUTPUT private: @@ -855,10 +857,13 @@ class MAGNUM_GL_EXPORT Context { Containers::Optional _detectedDrivers; + /** @todo these are all needed only until the state gets created and + then can be discarded -- what to do? we could avoid including + Array altogether */ /* True means known and disabled, false means known */ Containers::Array> _driverWorkarounds; Containers::Array _disabledExtensions; - InternalFlags _internalFlags; + Implementation::ContextConfigurationFlags _configurationFlags; }; #ifndef MAGNUM_TARGET_WEBGL @@ -903,8 +908,10 @@ class MAGNUM_GL_EXPORT Context::Configuration { * @ref Context::flags(). * @see @ref Flags, @ref setFlags() */ + #ifdef DOXYGEN_GENERATING_OUTPUT enum class Flag: UnsignedLong { - /* Keeping the 32-bit range reserved for actual GL context flags */ + /* Docs only, keep in sync with + Implementation::ContextConfigurationFlag please */ /** * Print only warnings and errors instead of the usual startup log @@ -934,13 +941,20 @@ class MAGNUM_GL_EXPORT Context::Configuration { */ GpuValidation = 1ull << 63 }; + #else + typedef Implementation::ContextConfigurationFlag Flag; + #endif /** * @brief Context setup flags * * @see @ref setFlags(), @ref GL::Context::Flags */ + #ifdef DOXYGEN_GENERATING_OUTPUT typedef Containers::EnumSet Flags; + #else + typedef Implementation::ContextConfigurationFlags Flags; + #endif /*implicit*/ Configuration(); @@ -1079,8 +1093,6 @@ class MAGNUM_GL_EXPORT Context::Configuration { } #endif -CORRADE_ENUMSET_OPERATORS(Context::Configuration::Flags) - /** @hideinitializer @brief Assert that given OpenGL version is supported @param version Version diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 4dc455378..e435c26aa 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -432,7 +432,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf /* Request debug context if --magnum-gpu-validation is enabled */ GLConfiguration::Flags glFlags = glConfiguration.flags(); - if(_context->internalFlags() & GL::Context::InternalFlag::GpuValidation) + if(_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) glFlags |= GLConfiguration::Flag::Debug; #ifdef GLFW_CONTEXT_NO_ERROR diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 0c59ac235..ba985b472 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -467,7 +467,7 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf /* Request debug context if --magnum-gpu-validation is enabled */ GLConfiguration::Flags glFlags = glConfiguration.flags(); - if(_context->internalFlags() & GL::Context::InternalFlag::GpuValidation) + if(_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) glFlags |= GLConfiguration::Flag::Debug; /* Set context version, if user-specified */ diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 9fca277c9..bad8f68b6 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -129,7 +129,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G --magnum-gpu-validation is enabled because otherwise it's fucking hard to discover what's to blame (lost > 3 hours already). See class docs for more info and a workaround. */ - if(extensionSupported(extensions, "EGL_KHR_debug") && magnumContext && (magnumContext->internalFlags() & GL::Context::InternalFlag::GpuValidation)) { + if(extensionSupported(extensions, "EGL_KHR_debug") && magnumContext && (magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) { auto eglDebugMessageControl = reinterpret_cast(eglGetProcAddress("eglDebugMessageControlKHR")); const EGLAttrib debugAttribs[] = { EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE, @@ -151,7 +151,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G if(!count) { Error e; e << "Platform::WindowlessEglApplication::tryCreateContext(): no EGL devices found, likely a driver issue"; - if(!magnumContext || !(magnumContext->internalFlags() & GL::Context::InternalFlag::GpuValidation)) + if(!magnumContext || !(magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) e << Debug::nospace << "; enable --magnum-gpu-validation to see additional info"; return; } @@ -195,7 +195,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G if(eglGetError() == EGL_BAD_DEVICE_EXT && !magnumContext->isDriverWorkaroundDisabled("nv-egl-crashy-query-device-attrib"_s)) continue; - if(magnumContext && (magnumContext->internalFlags() >= GL::Context::InternalFlag::DisplayVerboseInitializationLog)) + if(magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog)) Debug{} << "Platform::WindowlessEglApplication: eglQueryDeviceStringEXT(EGLDevice=" << Debug::nospace << selectedDevice << Debug::nospace << "):" << eglExtensions; EGLAttrib cudaDeviceNumber; @@ -210,7 +210,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G return; } - if(magnumContext && (magnumContext->internalFlags() >= GL::Context::InternalFlag::DisplayVerboseInitializationLog)) { + if(magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog)) { Debug{} << "Platform::WindowlessEglApplication: found" << count << "EGL devices, choosing EGL device" << selectedDevice << "for CUDA device" << configuration.cudaDevice(); } @@ -218,7 +218,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G } else { /* Print the log *before* calling eglQueryDevices() again, as the `count` gets overwritten by it */ - if(magnumContext && (magnumContext->internalFlags() >= GL::Context::InternalFlag::DisplayVerboseInitializationLog)) { + if(magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog)) { Debug{} << "Platform::WindowlessEglApplication: found" << count << "EGL devices, choosing device" << configuration.device(); } @@ -302,7 +302,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G #ifndef MAGNUM_TARGET_WEBGL /* Request debug context if --magnum-gpu-validation is enabled */ Configuration::Flags flags = configuration.flags(); - if(magnumContext && magnumContext->internalFlags() & GL::Context::InternalFlag::GpuValidation) + if(magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) flags |= Configuration::Flag::Debug; #endif diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index d94ea434c..29acee4fe 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -111,7 +111,7 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura /* Request debug context if --magnum-gpu-validation is enabled */ Configuration::Flags flags = configuration.flags(); - if(magnumContext && magnumContext->internalFlags() & GL::Context::InternalFlag::GpuValidation) + if(magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) flags |= Configuration::Flag::Debug; /* Optimistically choose core context first */ diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 76985b49b..dffbbc593 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -124,7 +124,7 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G /* Request debug context if --magnum-gpu-validation is enabled */ Configuration::Flags flags = configuration.flags(); - if(magnumContext && magnumContext->internalFlags() & GL::Context::InternalFlag::GpuValidation) + if(magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) flags |= Configuration::Flag::Debug; /* Optimistically choose core context first */ diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 5cb872171..b0341f8db 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -115,7 +115,7 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co /* Request debug context if --magnum-gpu-validation is enabled */ Configuration::Flags flags = configuration.flags(); - if(magnumContext && magnumContext->internalFlags() & GL::Context::InternalFlag::GpuValidation) + if(magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) flags |= Configuration::Flag::Debug; const EGLint attributes[] = { From 6acaa69d91f8309907767860620cbf2de55cf8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 25 Feb 2021 18:53:26 +0100 Subject: [PATCH 039/161] Platform: deduplicate verbose logging logic in WindowlessEglApplication. --- src/Magnum/Platform/WindowlessEglApplication.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index bad8f68b6..251c5dce1 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -102,6 +102,8 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G /* Otherwise find the display and initialize EGL */ { #ifndef MAGNUM_TARGET_WEBGL + const bool displayVerboseLog = magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog); + /* If relevant extensions are supported, try to find some display using those APIs, as that works reliably also when running headless. This would ideally use EGL 1.5 APIs but since we still want to support @@ -195,7 +197,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G if(eglGetError() == EGL_BAD_DEVICE_EXT && !magnumContext->isDriverWorkaroundDisabled("nv-egl-crashy-query-device-attrib"_s)) continue; - if(magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog)) + if(displayVerboseLog) Debug{} << "Platform::WindowlessEglApplication: eglQueryDeviceStringEXT(EGLDevice=" << Debug::nospace << selectedDevice << Debug::nospace << "):" << eglExtensions; EGLAttrib cudaDeviceNumber; @@ -210,7 +212,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G return; } - if(magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog)) { + if(displayVerboseLog) { Debug{} << "Platform::WindowlessEglApplication: found" << count << "EGL devices, choosing EGL device" << selectedDevice << "for CUDA device" << configuration.cudaDevice(); } @@ -218,7 +220,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G } else { /* Print the log *before* calling eglQueryDevices() again, as the `count` gets overwritten by it */ - if(magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog)) { + if(displayVerboseLog) { Debug{} << "Platform::WindowlessEglApplication: found" << count << "EGL devices, choosing device" << configuration.device(); } From 458c2c7757ecd0f09c9ae4cb536ba26ee4d1a24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 26 Feb 2021 12:31:48 +0100 Subject: [PATCH 040/161] Platform: take Flag::GpuValidation into account in all apps. Right now only the command-line variant of it was checked. Since on some platforms this requires the app to explicitly request a debug context, the app needs to handle the case when it's passed via a Configuration as well. --- src/Magnum/Platform/GlfwApplication.cpp | 5 +++-- src/Magnum/Platform/Sdl2Application.cpp | 5 +++-- .../Platform/Test/GlfwApplicationTest.cpp | 19 +++++++++++++------ .../Platform/Test/Sdl2ApplicationTest.cpp | 19 +++++++++++++------ .../Test/WindowlessEglApplicationTest.cpp | 13 ++++++++++--- .../Test/WindowlessGlxApplicationTest.cpp | 11 ++++++++--- .../Test/WindowlessWglApplicationTest.cpp | 10 +++++++--- .../WindowlessWindowsEglApplicationTest.cpp | 10 +++++++--- .../Platform/WindowlessEglApplication.cpp | 5 +++-- .../Platform/WindowlessGlxApplication.cpp | 5 +++-- .../Platform/WindowlessWglApplication.cpp | 5 +++-- .../WindowlessWindowsEglApplication.cpp | 5 +++-- 12 files changed, 76 insertions(+), 36 deletions(-) diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index e435c26aa..986413a6b 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -430,9 +430,10 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf glfwWindowHint(GLFW_SAMPLES, glConfiguration.sampleCount()); glfwWindowHint(GLFW_SRGB_CAPABLE, glConfiguration.isSrgbCapable()); - /* Request debug context if --magnum-gpu-validation is enabled */ + /* Request debug context if GpuValidation is enabled either via the + configuration or via command-line */ GLConfiguration::Flags glFlags = glConfiguration.flags(); - if(_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) + if((glFlags & GLConfiguration::Flag::GpuValidation) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) glFlags |= GLConfiguration::Flag::Debug; #ifdef GLFW_CONTEXT_NO_ERROR diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index ba985b472..c0770d5cd 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -465,9 +465,10 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf _dpiScaling = dpiScaling(configuration); const Vector2i scaledWindowSize = configuration.size()*_dpiScaling; - /* Request debug context if --magnum-gpu-validation is enabled */ + /* Request debug context if GpuValidation is enabled either via the + configuration or via command-line */ GLConfiguration::Flags glFlags = glConfiguration.flags(); - if(_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) + if((glFlags & GLConfiguration::Flag::GpuValidation) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) glFlags |= GLConfiguration::Flag::Debug; /* Set context version, if user-specified */ diff --git a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp index bfb8d4447..fd7a69e1d 100644 --- a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp +++ b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp @@ -110,6 +110,7 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform:: .addBooleanOption("always-on-top").setHelp("always-on-top", "always on top") #ifdef MAGNUM_TARGET_GL .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .addBooleanOption("gpu-validation").setHelp("gpu-validation", "like --magnum-gpu-validation, but specified via a Context::Configuration instead") #endif .parse(arguments.argc, arguments.argv); @@ -127,13 +128,19 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform:: if(args.isSet("always-on-top")) conf.addWindowFlags(Configuration::WindowFlag::AlwaysOnTop); #ifdef MAGNUM_TARGET_GL - if(args.isSet("quiet")) { - create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog)); - } else + GLConfiguration glConf; + if(args.isSet("quiet")) + glConf.addFlags(GLConfiguration::Flag::QuietLog); + if(args.isSet("gpu-validation")) + glConf.addFlags(GLConfiguration::Flag::GpuValidation); + create(conf, glConf); + #else + create(conf); + #endif + + #ifdef MAGNUM_TARGET_GL + Debug{} << "GL context flags:" << GL::Context::current().flags(); #endif - { - create(conf); - } /* For testing resize events */ Debug{} << "window size" << windowSize() diff --git a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp index 6565311ea..cd6844cbb 100644 --- a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp +++ b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp @@ -167,6 +167,7 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform:: #endif #ifdef MAGNUM_TARGET_GL .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .addBooleanOption("gpu-validation").setHelp("gpu-validation", "like --magnum-gpu-validation, but specified via a Context::Configuration instead") #endif .parse(arguments.argc, arguments.argv); @@ -188,13 +189,19 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform:: #endif #endif #ifdef MAGNUM_TARGET_GL - if(args.isSet("quiet")) { - create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog)); - } else + GLConfiguration glConf; + if(args.isSet("quiet")) + glConf.addFlags(GLConfiguration::Flag::QuietLog); + if(args.isSet("gpu-validation")) + glConf.addFlags(GLConfiguration::Flag::GpuValidation); + create(conf, glConf); + #else + create(conf); + #endif + + #if defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_WEBGL) + Debug{} << "GL context flags:" << GL::Context::current().flags(); #endif - { - create(conf); - } /* For testing resize events */ Debug{} << "window size" << windowSize() diff --git a/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp index d6464e6fd..ba828124f 100644 --- a/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp @@ -38,12 +38,19 @@ WindowlessEglApplicationTest::WindowlessEglApplicationTest(const Arguments& argu Utility::Arguments args; args.addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .addBooleanOption("gpu-validation").setHelp("gpu-validation", "like --magnum-gpu-validation, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); + Configuration conf; if(args.isSet("quiet")) - createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); - else - createContext(); + conf.addFlags(Configuration::Flag::QuietLog); + if(args.isSet("gpu-validation")) + conf.addFlags(Configuration::Flag::GpuValidation); + createContext(conf); + + #ifndef MAGNUM_TARGET_WEBGL + Debug{} << "GL context flags:" << GL::Context::current().flags(); + #endif } }}}} diff --git a/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp index e75b3d9c5..298701eaf 100644 --- a/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp @@ -38,12 +38,17 @@ WindowlessGlxApplicationTest::WindowlessGlxApplicationTest(const Arguments& argu Utility::Arguments args; args.addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .addBooleanOption("gpu-validation").setHelp("gpu-validation", "like --magnum-gpu-validation, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); + Configuration conf; if(args.isSet("quiet")) - createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); - else - createContext(); + conf.addFlags(Configuration::Flag::QuietLog); + if(args.isSet("gpu-validation")) + conf.addFlags(Configuration::Flag::GpuValidation); + createContext(conf); + + Debug{} << "GL context flags:" << GL::Context::current().flags(); } }}}} diff --git a/src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp index 82b7baaa2..b71193246 100644 --- a/src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessWglApplicationTest.cpp @@ -38,12 +38,16 @@ WindowlessWglApplicationTest::WindowlessWglApplicationTest(const Arguments& argu Utility::Arguments args; args.addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .addBooleanOption("gpu-validation").setHelp("gpu-validation", "like --magnum-gpu-validation, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); + Configuration conf; if(args.isSet("quiet")) - createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); - else - createContext(); + conf.addFlags(Configuration::Flag::QuietLog); + /* No verbose logs in this app */ + if(args.isSet("gpu-validation")) + conf.addFlags(Configuration::Flag::GpuValidation); + createContext(conf); } }}}} diff --git a/src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp index 9bc627507..03595ea5b 100644 --- a/src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessWindowsEglApplicationTest.cpp @@ -38,12 +38,16 @@ WindowlessWindowsEglApplicationTest::WindowlessWindowsEglApplicationTest(const A Utility::Arguments args; args.addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .addBooleanOption("gpu-validation").setHelp("gpu-validation", "like --magnum-gpu-validation, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); + Configuration conf; if(args.isSet("quiet")) - createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); - else - createContext(); + conf.addFlags(Configuration::Flag::QuietLog); + /* No verbose logs in this app */ + if(args.isSet("gpu-validation")) + conf.addFlags(Configuration::Flag::GpuValidation); + createContext(conf); } }}}} diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 251c5dce1..e2e85e809 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -302,9 +302,10 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G } #ifndef MAGNUM_TARGET_WEBGL - /* Request debug context if --magnum-gpu-validation is enabled */ + /* Request debug context if GpuValidation is enabled either via the + configuration or via command-line */ Configuration::Flags flags = configuration.flags(); - if(magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) + if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; #endif diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index 29acee4fe..ce8e23092 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -109,9 +109,10 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura /* Get pointer to proper context creation function */ const PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast(glXGetProcAddress(reinterpret_cast("glXCreateContextAttribsARB"))); - /* Request debug context if --magnum-gpu-validation is enabled */ + /* Request debug context if GpuValidation is enabled either via the + configuration or via command-line */ Configuration::Flags flags = configuration.flags(); - if(magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) + if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; /* Optimistically choose core context first */ diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index dffbbc593..e01037773 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -122,9 +122,10 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G typedef HGLRC(WINAPI*PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*); const PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = reinterpret_cast( wglGetProcAddress(reinterpret_cast("wglCreateContextAttribsARB"))); - /* Request debug context if --magnum-gpu-validation is enabled */ + /* Request debug context if GpuValidation is enabled either via the + configuration or via command-line */ Configuration::Flags flags = configuration.flags(); - if(magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) + if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; /* Optimistically choose core context first */ diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index b0341f8db..8a9707d74 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -113,9 +113,10 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co return; } - /* Request debug context if --magnum-gpu-validation is enabled */ + /* Request debug context if GpuValidation is enabled either via the + configuration or via command-line */ Configuration::Flags flags = configuration.flags(); - if(magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation) + if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; const EGLint attributes[] = { From a4a239d0f4c1864c6403242a2dd4668a0a43c275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 26 Feb 2021 12:37:23 +0100 Subject: [PATCH 041/161] Platform: take into account Flag::VerboseLog in WindowlessEglApplication. The app does its own EGL-specific verbose printing and thus should recognize this option the same way as GL::Context does. Right now it was only taking into account the command-line parameters and not the new Configuration. --- src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp | 5 +++++ src/Magnum/Platform/WindowlessEglApplication.cpp | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp index ba828124f..603a32abb 100644 --- a/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessEglApplicationTest.cpp @@ -38,12 +38,17 @@ WindowlessEglApplicationTest::WindowlessEglApplicationTest(const Arguments& argu Utility::Arguments args; args.addSkippedPrefix("magnum", "engine-specific options") .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") + .addBooleanOption("verbose").setHelp("verbose", "like --magnum-log verbose, but specified via a Context::Configuration instead") .addBooleanOption("gpu-validation").setHelp("gpu-validation", "like --magnum-gpu-validation, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); Configuration conf; if(args.isSet("quiet")) conf.addFlags(Configuration::Flag::QuietLog); + /* Additional EGL-specific output is printed by the app, verify we take + the Configuration option into account as well, not just command line */ + if(args.isSet("verbose")) + conf.addFlags(Configuration::Flag::VerboseLog); if(args.isSet("gpu-validation")) conf.addFlags(Configuration::Flag::GpuValidation); createContext(conf); diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index e2e85e809..844fe7e38 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -102,7 +102,9 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G /* Otherwise find the display and initialize EGL */ { #ifndef MAGNUM_TARGET_WEBGL - const bool displayVerboseLog = magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog); + /* Display verbose log if specified either on command line or in + Configuration but not if the command line overrides it to be quiet */ + const bool displayVerboseLog = ((configuration.flags() & Configuration::Flag::VerboseLog) && (!magnumContext || !(magnumContext->configurationFlags() & GL::Context::Configuration::Flag::QuietLog))) || (magnumContext && (magnumContext->configurationFlags() >= GL::Context::Configuration::Flag::VerboseLog)); /* If relevant extensions are supported, try to find some display using those APIs, as that works reliably also when running headless. This From cef4719d3e0eee7e73a3c21053233197649b7df6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 26 Feb 2021 12:38:48 +0100 Subject: [PATCH 042/161] Platform: document why particular things aren't tested. --- src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp | 9 ++++++--- src/Magnum/Platform/Test/GlfwApplicationTest.cpp | 2 ++ src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp | 2 ++ .../Platform/Test/WindowlessCglApplicationTest.cpp | 1 + .../Platform/Test/WindowlessGlxApplicationTest.cpp | 1 + .../Platform/Test/WindowlessIosApplicationTest.cpp | 1 + 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp index e330277e4..d6c7f068c 100644 --- a/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp +++ b/src/Magnum/Platform/Test/EmscriptenApplicationTest.cpp @@ -170,10 +170,13 @@ EmscriptenApplicationTest::EmscriptenApplicationTest(const Arguments& arguments) Configuration conf; conf.setWindowFlags(Configuration::WindowFlag::Resizable); + GLConfiguration glConf; if(args.isSet("quiet")) - create(conf, GLConfiguration{}.addFlags(GLConfiguration::Flag::QuietLog)); - else - create(conf); + glConf.addFlags(GLConfiguration::Flag::QuietLog); + /* No GL-specific verbose log in EmscriptenApplication that we'd need to + handle explicitly */ + /* No GPU validation on WebGL */ + create(conf, glConf); Debug{} << "window size" << windowSize() #ifdef MAGNUM_TARGET_GL diff --git a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp index fd7a69e1d..de10695bb 100644 --- a/src/Magnum/Platform/Test/GlfwApplicationTest.cpp +++ b/src/Magnum/Platform/Test/GlfwApplicationTest.cpp @@ -131,6 +131,8 @@ GlfwApplicationTest::GlfwApplicationTest(const Arguments& arguments): Platform:: GLConfiguration glConf; if(args.isSet("quiet")) glConf.addFlags(GLConfiguration::Flag::QuietLog); + /* No GL-specific verbose log in GlfwApplication that we'd need to handle + explicitly */ if(args.isSet("gpu-validation")) glConf.addFlags(GLConfiguration::Flag::GpuValidation); create(conf, glConf); diff --git a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp index cd6844cbb..edd714162 100644 --- a/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp +++ b/src/Magnum/Platform/Test/Sdl2ApplicationTest.cpp @@ -192,6 +192,8 @@ Sdl2ApplicationTest::Sdl2ApplicationTest(const Arguments& arguments): Platform:: GLConfiguration glConf; if(args.isSet("quiet")) glConf.addFlags(GLConfiguration::Flag::QuietLog); + /* No GL-specific verbose log in Sdl2Application that we'd need to handle + explicitly */ if(args.isSet("gpu-validation")) glConf.addFlags(GLConfiguration::Flag::GpuValidation); create(conf, glConf); diff --git a/src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp index a90c98eac..948532418 100644 --- a/src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessCglApplicationTest.cpp @@ -40,6 +40,7 @@ WindowlessCglApplicationTest::WindowlessCglApplicationTest(const Arguments& argu .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); + /* No verbose logs in the app, no GPU validation in CGL either */ if(args.isSet("quiet")) createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); else diff --git a/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp index 298701eaf..4e8719e51 100644 --- a/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessGlxApplicationTest.cpp @@ -44,6 +44,7 @@ WindowlessGlxApplicationTest::WindowlessGlxApplicationTest(const Arguments& argu Configuration conf; if(args.isSet("quiet")) conf.addFlags(Configuration::Flag::QuietLog); + /* No verbose logs in this app */ if(args.isSet("gpu-validation")) conf.addFlags(Configuration::Flag::GpuValidation); createContext(conf); diff --git a/src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp b/src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp index a1f042616..11b7c6903 100644 --- a/src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp +++ b/src/Magnum/Platform/Test/WindowlessIosApplicationTest.cpp @@ -40,6 +40,7 @@ WindowlessIosApplicationTest::WindowlessIosApplicationTest(const Arguments& argu .addBooleanOption("quiet").setHelp("quiet", "like --magnum-log quiet, but specified via a Context::Configuration instead") .parse(arguments.argc, arguments.argv); + /* No verbose logs in the app, no GPU validation in EAGL either */ if(args.isSet("quiet")) createContext(Configuration{}.addFlags(Configuration::Flag::QuietLog)); else From 5d05acbf1faf31d48a6fbcc784af3cb9c7a41522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 26 Feb 2021 13:11:44 +0100 Subject: [PATCH 043/161] Platform: explicitly destroy GL::Context before the GL context. So in case it touches the GL state in some way, it doesn't do that on an already destroyed context. The windowless apps do this all implicitly due to the WindowlessGLContext encapsulation. --- src/Magnum/Platform/AbstractXApplication.cpp | 2 ++ src/Magnum/Platform/AndroidApplication.cpp | 4 ++++ src/Magnum/Platform/EmscriptenApplication.cpp | 2 ++ src/Magnum/Platform/GlfwApplication.cpp | 6 ++++++ src/Magnum/Platform/Sdl2Application.cpp | 2 ++ 5 files changed, 16 insertions(+) diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index 99f34a05d..6a98a0ee6 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -109,6 +109,8 @@ bool AbstractXApplication::tryCreate(const Configuration& configuration, const G } AbstractXApplication::~AbstractXApplication() { + /* Destroy Magnum context first to avoid it potentially accessing the + now-destroyed GL context after */ _context.reset(); /* Shut down context handler */ diff --git a/src/Magnum/Platform/AndroidApplication.cpp b/src/Magnum/Platform/AndroidApplication.cpp index b45ea7d77..e078c323f 100644 --- a/src/Magnum/Platform/AndroidApplication.cpp +++ b/src/Magnum/Platform/AndroidApplication.cpp @@ -77,6 +77,10 @@ AndroidApplication::AndroidApplication(const Arguments& arguments, NoCreateT): _ } AndroidApplication::~AndroidApplication() { + /* Destroy Magnum context first to avoid it potentially accessing the + now-destroyed GL context after */ + _context.reset(); + eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(_display, _glContext); eglDestroySurface(_display, _surface); diff --git a/src/Magnum/Platform/EmscriptenApplication.cpp b/src/Magnum/Platform/EmscriptenApplication.cpp index 86d826c6c..f8574e4a0 100644 --- a/src/Magnum/Platform/EmscriptenApplication.cpp +++ b/src/Magnum/Platform/EmscriptenApplication.cpp @@ -260,6 +260,8 @@ EmscriptenApplication::EmscriptenApplication(const Arguments& arguments, NoCreat EmscriptenApplication::~EmscriptenApplication() { #ifdef MAGNUM_TARGET_GL + /* Destroy Magnum context first to avoid it potentially accessing the + now-destroyed GL context after */ _context.reset(); emscripten_webgl_destroy_context(_glContext); diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 986413a6b..32d0d68f4 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -668,6 +668,12 @@ void GlfwApplication::setupCallbacks() { } GlfwApplication::~GlfwApplication() { + #ifdef MAGNUM_TARGET_GL + /* Destroy Magnum context first to avoid it potentially accessing the + now-destroyed GL context after */ + _context.reset(); + #endif + glfwDestroyWindow(_window); for(auto& cursor: _cursors) glfwDestroyCursor(cursor); diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index c0770d5cd..28f7c2d40 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -796,6 +796,8 @@ Sdl2Application::~Sdl2Application() { all. */ #ifdef MAGNUM_TARGET_GL + /* Destroy Magnum context first to avoid it potentially accessing the + now-destroyed GL context after */ _context.reset(); #ifndef CORRADE_TARGET_EMSCRIPTEN From 6dafbd0c14dc1fca0039edaa42ab8afebb5e50bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 26 Feb 2021 13:20:30 +0100 Subject: [PATCH 044/161] Platform: since we #include the Context anyway, no need to PIMPL it. This removes one unnecessary allocation from each application startup. In some cases of the windowless apps the Platform::GLContext could be put directly into the class, in other cases it had to be wrapped in an Optional because we need delayed construction and/or earlier destruction. --- src/Magnum/Platform/AbstractXApplication.cpp | 5 ++--- src/Magnum/Platform/AbstractXApplication.h | 8 +++++--- src/Magnum/Platform/AndroidApplication.cpp | 5 ++--- src/Magnum/Platform/AndroidApplication.h | 7 +++++-- src/Magnum/Platform/EmscriptenApplication.cpp | 5 ++--- src/Magnum/Platform/EmscriptenApplication.h | 15 +++++++++++++-- src/Magnum/Platform/GlfwApplication.cpp | 5 ++--- src/Magnum/Platform/GlfwApplication.h | 8 +++++--- src/Magnum/Platform/Sdl2Application.cpp | 5 ++--- src/Magnum/Platform/Sdl2Application.h | 8 +++++--- src/Magnum/Platform/WindowlessCglApplication.cpp | 9 ++++----- src/Magnum/Platform/WindowlessCglApplication.h | 7 ++----- src/Magnum/Platform/WindowlessEglApplication.cpp | 5 ++--- src/Magnum/Platform/WindowlessEglApplication.h | 9 +++++---- src/Magnum/Platform/WindowlessGlxApplication.cpp | 9 ++++----- src/Magnum/Platform/WindowlessGlxApplication.h | 6 ++---- src/Magnum/Platform/WindowlessIosApplication.h | 6 ++---- src/Magnum/Platform/WindowlessIosApplication.mm | 8 ++++---- src/Magnum/Platform/WindowlessWglApplication.cpp | 9 ++++----- src/Magnum/Platform/WindowlessWglApplication.h | 6 ++---- .../Platform/WindowlessWindowsEglApplication.cpp | 9 ++++----- .../Platform/WindowlessWindowsEglApplication.h | 6 ++---- 22 files changed, 80 insertions(+), 80 deletions(-) diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index 6a98a0ee6..d816e8363 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -29,7 +29,6 @@ #include #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" #include "Implementation/AbstractContextHandler.h" @@ -42,7 +41,7 @@ AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandle create(configuration, glConfiguration); } -AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, NoCreateT): _contextHandler{contextHandler}, _context{new GLContext{NoCreate, arguments.argc, arguments.argv}}, _flags{Flag::Redraw} {} +AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, NoCreateT): _contextHandler{contextHandler}, _context{Containers::InPlaceInit, NoCreate, arguments.argc, arguments.argv}, _flags{Flag::Redraw} {} void AbstractXApplication::create() { create({}); } @@ -111,7 +110,7 @@ bool AbstractXApplication::tryCreate(const Configuration& configuration, const G AbstractXApplication::~AbstractXApplication() { /* Destroy Magnum context first to avoid it potentially accessing the now-destroyed GL context after */ - _context.reset(); + _context = Containers::NullOpt; /* Shut down context handler */ _contextHandler.reset(); diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index adc4193ef..e5e60c322 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -35,6 +35,7 @@ #ifdef MAGNUM_TARGET_GL #include #include +#include #include #include @@ -60,9 +61,8 @@ typedef int Bool; #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/Context.h" #include "Magnum/Math/Vector2.h" -#include "Magnum/Platform/Platform.h" +#include "Magnum/Platform/GLContext.h" namespace Magnum { namespace Platform { @@ -319,7 +319,9 @@ class AbstractXApplication { Atom _deleteWindow{}; Containers::Pointer> _contextHandler; - Containers::Pointer _context; + /* Has to be in an Optional because it gets explicitly destroyed before + the GL context */ + Containers::Optional _context; int _exitCode = 0; /** @todo Get this from the created window */ diff --git a/src/Magnum/Platform/AndroidApplication.cpp b/src/Magnum/Platform/AndroidApplication.cpp index e078c323f..f3ee497f0 100644 --- a/src/Magnum/Platform/AndroidApplication.cpp +++ b/src/Magnum/Platform/AndroidApplication.cpp @@ -30,7 +30,6 @@ #include #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" #include "Magnum/Platform/ScreenedApplication.hpp" #include "Implementation/Egl.h" @@ -71,7 +70,7 @@ AndroidApplication::AndroidApplication(const Arguments& arguments, const Configu create(configuration, glConfiguration); } -AndroidApplication::AndroidApplication(const Arguments& arguments, NoCreateT): _state{arguments}, _context{new GLContext{NoCreate, 0, nullptr}} { +AndroidApplication::AndroidApplication(const Arguments& arguments, NoCreateT): _state{arguments}, _context{Containers::InPlaceInit, NoCreate} { /* Redirect debug output to Android log */ _logOutput.reset(new LogOutput); } @@ -79,7 +78,7 @@ AndroidApplication::AndroidApplication(const Arguments& arguments, NoCreateT): _ AndroidApplication::~AndroidApplication() { /* Destroy Magnum context first to avoid it potentially accessing the now-destroyed GL context after */ - _context.reset(); + _context = Containers::NullOpt; eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(_display, _glContext); diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index bcc28757d..6d00d55c0 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -32,13 +32,14 @@ #endif #include +#include #include #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/Context.h" #include "Magnum/Math/Vector4.h" #include "Magnum/Platform/Platform.h" +#include "Magnum/Platform/GLContext.h" #if defined(CORRADE_TARGET_ANDROID) || defined(DOXYGEN_GENERATING_OUTPUT) #include @@ -435,7 +436,9 @@ class AndroidApplication { EGLContext _glContext; Vector2i _previousMouseMovePosition{-1}; - Containers::Pointer _context; + /* Has to be in an Optional because it gets explicitly destroyed before + the GL context */ + Containers::Optional _context; Containers::Pointer _logOutput; CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) diff --git a/src/Magnum/Platform/EmscriptenApplication.cpp b/src/Magnum/Platform/EmscriptenApplication.cpp index f8574e4a0..5e3e018ce 100644 --- a/src/Magnum/Platform/EmscriptenApplication.cpp +++ b/src/Magnum/Platform/EmscriptenApplication.cpp @@ -40,7 +40,6 @@ #ifdef MAGNUM_TARGET_GL #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" #endif /** @todo drop once we don't support < 1.38.27 anymore */ @@ -237,7 +236,7 @@ EmscriptenApplication::EmscriptenApplication(const Arguments& arguments, NoCreat { Utility::Arguments args{Implementation::windowScalingArguments()}; #ifdef MAGNUM_TARGET_GL - _context.reset(new GLContext{NoCreate, args, arguments.argc, arguments.argv}); + _context.emplace(NoCreate, args, arguments.argc, arguments.argv); #else args.parse(arguments.argc, arguments.argv); #endif @@ -262,7 +261,7 @@ EmscriptenApplication::~EmscriptenApplication() { #ifdef MAGNUM_TARGET_GL /* Destroy Magnum context first to avoid it potentially accessing the now-destroyed GL context after */ - _context.reset(); + _context = Containers::NullOpt; emscripten_webgl_destroy_context(_glContext); #endif diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index 3d7d0b81f..585c24af1 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -36,14 +36,22 @@ #include #include + +/* Needed by the MAGNUM_EMSCRIPTENAPPLICATION_MAIN() macro */ +/** @todo use an Optional */ #include #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/Context.h" #include "Magnum/Math/Vector4.h" #include "Magnum/Platform/Platform.h" +#ifdef MAGNUM_TARGET_GL +#include + +#include "Magnum/Platform/GLContext.h" +#endif + #if defined(CORRADE_TARGET_EMSCRIPTEN) || defined(DOXYGEN_GENERATING_OUTPUT) #ifndef DOXYGEN_GENERATING_OUTPUT @@ -902,7 +910,10 @@ class EmscriptenApplication { #ifdef MAGNUM_TARGET_GL EMSCRIPTEN_WEBGL_CONTEXT_HANDLE _glContext{}; - Containers::Pointer _context; + /* Has to be in an Optional because we delay-create it in a constructor + with populated Arguments and it gets explicitly destroyed before the + GL context */ + Containers::Optional _context; #endif /* These are saved from command-line arguments */ diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 32d0d68f4..5e51f14ac 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -44,7 +44,6 @@ #ifdef MAGNUM_TARGET_GL #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" #endif namespace Magnum { namespace Platform { @@ -82,7 +81,7 @@ GlfwApplication::GlfwApplication(const Arguments& arguments, NoCreateT): { Utility::Arguments args{Implementation::windowScalingArguments()}; #ifdef MAGNUM_TARGET_GL - _context.reset(new GLContext{NoCreate, args, arguments.argc, arguments.argv}); + _context.emplace(NoCreate, args, arguments.argc, arguments.argv); #else /** @todo this is duplicated here and in Sdl2Application, figure out a nice non-duplicated way to handle this */ @@ -671,7 +670,7 @@ GlfwApplication::~GlfwApplication() { #ifdef MAGNUM_TARGET_GL /* Destroy Magnum context first to avoid it potentially accessing the now-destroyed GL context after */ - _context.reset(); + _context = Containers::NullOpt; #endif glfwDestroyWindow(_window); diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index b0135b8f8..2d27a7180 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -35,7 +35,6 @@ #include #include #include -#include #include "Magnum/Magnum.h" #include "Magnum/Tags.h" @@ -43,7 +42,7 @@ #include "Magnum/Platform/Platform.h" #ifdef MAGNUM_TARGET_GL -#include "Magnum/GL/Context.h" +#include "Magnum/Platform/GLContext.h" #endif #ifndef DOXYGEN_GENERATING_OUTPUT @@ -757,7 +756,10 @@ class GlfwApplication { GLFWwindow* _window{nullptr}; Flags _flags; #ifdef MAGNUM_TARGET_GL - Containers::Pointer _context; + /* Has to be in an Optional because we delay-create it in a constructor + with populated Arguments and it gets explicitly destroyed before the + GL context */ + Containers::Optional _context; #endif int _exitCode = 0; diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 28f7c2d40..3b815f653 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -56,7 +56,6 @@ #ifdef MAGNUM_TARGET_GL #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" #endif #if defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT) @@ -125,7 +124,7 @@ Sdl2Application::Sdl2Application(const Arguments& arguments, NoCreateT): { Utility::Arguments args{Implementation::windowScalingArguments()}; #ifdef MAGNUM_TARGET_GL - _context.reset(new GLContext{NoCreate, args, arguments.argc, arguments.argv}); + _context.emplace(NoCreate, args, arguments.argc, arguments.argv); #else /** @todo this is duplicated here and in GlfwApplication, figure out a nice non-duplicated way to handle this */ @@ -798,7 +797,7 @@ Sdl2Application::~Sdl2Application() { #ifdef MAGNUM_TARGET_GL /* Destroy Magnum context first to avoid it potentially accessing the now-destroyed GL context after */ - _context.reset(); + _context = Containers::NullOpt; #ifndef CORRADE_TARGET_EMSCRIPTEN if(_glContext) SDL_GL_DeleteContext(_glContext); diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index b35d10b5f..acb6279be 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -34,7 +34,6 @@ #include #include #include -#include #include "Magnum/Magnum.h" #include "Magnum/Tags.h" @@ -42,7 +41,7 @@ #include "Magnum/Platform/Platform.h" #ifdef MAGNUM_TARGET_GL -#include "Magnum/GL/Context.h" +#include "Magnum/Platform/GLContext.h" #endif #ifdef CORRADE_TARGET_WINDOWS /* Windows version of SDL2 redefines main(), we don't want that */ @@ -1209,7 +1208,10 @@ class Sdl2Application { #ifndef CORRADE_TARGET_EMSCRIPTEN SDL_GLContext _glContext{}; #endif - Containers::Pointer _context; + /* Has to be in an Optional because we delay-create it in a constructor + with populated Arguments and it gets explicitly destroyed before the + GL context */ + Containers::Optional _context; #endif Flags _flags; diff --git a/src/Magnum/Platform/WindowlessCglApplication.cpp b/src/Magnum/Platform/WindowlessCglApplication.cpp index 3fb0d1b7e..146780ab7 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.cpp +++ b/src/Magnum/Platform/WindowlessCglApplication.cpp @@ -32,7 +32,6 @@ #include #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" namespace Magnum { namespace Platform { @@ -114,7 +113,7 @@ WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, c createContext(configuration); } -WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new GLContext{NoCreate, arguments.argc, arguments.argv}} {} +WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{NoCreate, arguments.argc, arguments.argv} {} WindowlessCglApplication::~WindowlessCglApplication() = default; @@ -125,10 +124,10 @@ void WindowlessCglApplication::createContext(const Configuration& configuration) } bool WindowlessCglApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false); + CORRADE_ASSERT(_context.version() == GL::Version::None, "Platform::WindowlessCglApplication::tryCreateContext(): context already created", false); - WindowlessCglContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) + WindowlessCglContext glContext{configuration, &_context}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context.tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index 07e908bff..a8f58a46d 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -35,12 +35,9 @@ #include "Magnum/configure.h" #ifdef MAGNUM_TARGET_GL -#include - #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/Context.h" -#include "Magnum/Platform/Platform.h" +#include "Magnum/Platform/GLContext.h" #ifndef DOXYGEN_GENERATING_OUTPUT #define GL_SILENCE_DEPRECATION /* YES I KNOW, APPLE! FFS */ @@ -399,7 +396,7 @@ class WindowlessCglApplication { private: WindowlessCglContext _glContext; - Containers::Pointer _context; + Platform::GLContext _context; }; /** @hideinitializer diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 844fe7e38..9b8e3547b 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -36,7 +36,6 @@ #include #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" #include "Implementation/Egl.h" @@ -555,7 +554,7 @@ WindowlessEglApplication::WindowlessEglApplication(const Arguments& arguments, N .addOption("cuda-device", "").setHelp("cuda-device", "CUDA device to use. Takes precedence over --magnum-device.", "N") .setFromEnvironment("cuda-device"); #endif - _context.reset(new GLContext{NoCreate, args, arguments.argc, arguments.argv}); + _context.emplace(NoCreate, args, arguments.argc, arguments.argv); #ifndef MAGNUM_TARGET_WEBGL if(args.value("device").empty()) @@ -588,7 +587,7 @@ bool WindowlessEglApplication::tryCreateContext(const Configuration& configurati .setCudaDevice(_commandLineCudaDevice); #endif - WindowlessEglContext glContext{mergedConfiguration, _context.get()}; + WindowlessEglContext glContext{mergedConfiguration, &*_context}; if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) return false; diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index 22340bfd1..6dbd46279 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -50,7 +50,7 @@ #undef Button4 #undef Button5 #include -#include +#include #ifndef DOXYGEN_GENERATING_OUTPUT /* Unfortunately Xlib *needs* the Bool type, so provide a typedef instead */ @@ -58,9 +58,8 @@ typedef int Bool; #endif #include "Magnum/Magnum.h" -#include "Magnum/GL/Context.h" #include "Magnum/Tags.h" -#include "Magnum/Platform/Platform.h" +#include "Magnum/Platform/GLContext.h" namespace Magnum { namespace Platform { @@ -689,7 +688,9 @@ class WindowlessEglApplication { private: WindowlessEglContext _glContext; - Containers::Pointer _context; + /* Unlike other windowless apps has to be in an Optional because we + delay-create it in a constructor with populated Arguments */ + Containers::Optional _context; #ifndef MAGNUM_TARGET_WEBGL /* These are saved from command-line arguments */ diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index ce8e23092..0d0cb3fb4 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -32,7 +32,6 @@ #include #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" /* Saner way to define the insane Xlib macros (anyway, FUCK YOU XLIB) */ namespace { enum { None = 0, Success = 0 }; } @@ -288,7 +287,7 @@ WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, c createContext(configuration); } -WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new GLContext{NoCreate, arguments.argc, arguments.argv}} {} +WindowlessGlxApplication::WindowlessGlxApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{NoCreate, arguments.argc, arguments.argv} {} void WindowlessGlxApplication::createContext() { createContext({}); } @@ -297,10 +296,10 @@ void WindowlessGlxApplication::createContext(const Configuration& configuration) } bool WindowlessGlxApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false); + CORRADE_ASSERT(_context.version() == GL::Version::None, "Platform::WindowlessGlxApplication::tryCreateContext(): context already created", false); - WindowlessGlxContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) + WindowlessGlxContext glContext{configuration, &_context}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context.tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 1c1b0f85b..639625be5 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -34,13 +34,11 @@ #ifdef MAGNUM_TARGET_GL #include -#include /* Include our GL headers first to avoid conflicts */ #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/Context.h" -#include "Magnum/Platform/Platform.h" +#include "Magnum/Platform/GLContext.h" #include #include @@ -511,7 +509,7 @@ class WindowlessGlxApplication { private: WindowlessGlxContext _glContext; - Containers::Pointer _context; + Platform::GLContext _context; }; /** @hideinitializer diff --git a/src/Magnum/Platform/WindowlessIosApplication.h b/src/Magnum/Platform/WindowlessIosApplication.h index fdfb7cca2..d02e92b07 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.h +++ b/src/Magnum/Platform/WindowlessIosApplication.h @@ -33,12 +33,10 @@ #ifdef MAGNUM_TARGET_GL #include -#include #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/Context.h" -#include "Magnum/Platform/Platform.h" +#include "Magnum/Platform/GLContext.h" #ifdef __OBJC__ @class EAGLContext; @@ -354,7 +352,7 @@ class WindowlessIosApplication { private: WindowlessIosContext _glContext; - Containers::Pointer _context; + Platform::GLContext _context; }; /** @hideinitializer diff --git a/src/Magnum/Platform/WindowlessIosApplication.mm b/src/Magnum/Platform/WindowlessIosApplication.mm index 83756aeb8..a174de8e2 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.mm +++ b/src/Magnum/Platform/WindowlessIosApplication.mm @@ -90,7 +90,7 @@ WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments, c createContext(configuration); } -WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new GLContext{NoCreate, arguments.argc, arguments.argv}} {} +WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{NoCreate, arguments.argc, arguments.argv} {} void WindowlessIosApplication::createContext() { createContext({}); } @@ -99,10 +99,10 @@ void WindowlessIosApplication::createContext(const Configuration& configuration) } bool WindowlessIosApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessIosApplication::tryCreateContext(): context already created", false); + CORRADE_ASSERT(_context.version() == GL::Version::None, "Platform::WindowlessIosApplication::tryCreateContext(): context already created", false); - WindowlessIosContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate()) + WindowlessIosContext glContext{configuration, &_context}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context.tryCreate()) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index e01037773..5f9482f3c 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -31,7 +31,6 @@ #include #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" #ifndef DOXYGEN_GENERATING_OUTPUT /* Define stuff that we need because I can't be bothered with creating a new @@ -273,7 +272,7 @@ WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, c createContext(configuration); } -WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new GLContext{NoCreate, arguments.argc, arguments.argv}} {} +WindowlessWglApplication::WindowlessWglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{NoCreate, arguments.argc, arguments.argv} {} void WindowlessWglApplication::createContext() { createContext({}); } @@ -282,10 +281,10 @@ void WindowlessWglApplication::createContext(const Configuration& configuration) } bool WindowlessWglApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == GL::Version::None, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false); + CORRADE_ASSERT(_context.version() == GL::Version::None, "Platform::WindowlessWglApplication::tryCreateContext(): context already created", false); - WindowlessWglContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) + WindowlessWglContext glContext{configuration, &_context}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context.tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 6bf035a4b..71db719f2 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -38,12 +38,10 @@ #endif #include #include -#include #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/Context.h" -#include "Magnum/Platform/Platform.h" +#include "Magnum/Platform/GLContext.h" #ifndef DOXYGEN_GENERATING_OUTPUT /* Define stuff that we need because I can't be bothered with creating a new @@ -496,7 +494,7 @@ class WindowlessWglApplication { private: WindowlessWglContext _glContext; - Containers::Pointer _context; + Platform::GLContext _context; }; /** @hideinitializer diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 8a9707d74..b153ac85d 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -29,7 +29,6 @@ #include #include "Magnum/GL/Version.h" -#include "Magnum/Platform/GLContext.h" #include "Implementation/Egl.h" @@ -191,7 +190,7 @@ WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments createContext(configuration); } -WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{new GLContext{NoCreate, arguments.argc, arguments.argv}} {} +WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments, NoCreateT): _glContext{NoCreate}, _context{NoCreate, arguments.argc, arguments.argv} {} void WindowlessWindowsEglApplication::createContext() { createContext({}); } @@ -200,10 +199,10 @@ void WindowlessWindowsEglApplication::createContext(const Configuration& configu } bool WindowlessWindowsEglApplication::tryCreateContext(const Configuration& configuration) { - CORRADE_ASSERT(_context->version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false); + CORRADE_ASSERT(_context.version() == Version::None, "Platform::WindowlessWindowsEglApplication::tryCreateContext(): context already created", false); - WindowlessWindowsEglContext glContext{configuration, _context.get()}; - if(!glContext.isCreated() || !glContext.makeCurrent() || !_context->tryCreate(configuration)) + WindowlessWindowsEglContext glContext{configuration, &_context}; + if(!glContext.isCreated() || !glContext.makeCurrent() || !_context.tryCreate(configuration)) return false; _glContext = std::move(glContext); diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 80694d9b3..64c4701bc 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -40,12 +40,10 @@ #include #include #include -#include #include "Magnum/Magnum.h" #include "Magnum/Tags.h" -#include "Magnum/GL/Context.h" -#include "Magnum/Platform/Platform.h" +#include "Magnum/Platform/GLContext.h" namespace Magnum { namespace Platform { @@ -468,7 +466,7 @@ class WindowlessWindowsEglApplication { private: WindowlessWindowsEglContext _glContext; - Containers::Pointer _context; + Platform::GLContext _context; }; /** @hideinitializer From 532d72e1aaa4b8b86f62d97c2be4aa91c6e1a015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 26 Feb 2021 17:23:52 +0100 Subject: [PATCH 045/161] GL: put all internal Context State substructures in a single allocation. This means that instead of 12 separate allocations we have just one, allocating everything together in a contiguous piece of memory. That should be also a bit more cache friendly when accessing the state as it's not scattered around the memory like crazy. Because there are no Pointer indirections needed anymore, the State members are just references now. That resulted in a lot of sweeping changes around the whole GL library, but they're all trivial, changing `->` to `.`, mostly. There's two more nested allocations in the TextureState struct, will take care of them in a separate commit. --- src/Magnum/GL/AbstractFramebuffer.cpp | 58 ++-- src/Magnum/GL/AbstractObject.cpp | 2 +- src/Magnum/GL/AbstractQuery.cpp | 10 +- src/Magnum/GL/AbstractShaderProgram.cpp | 116 ++++---- src/Magnum/GL/AbstractTexture.cpp | 250 +++++++++--------- src/Magnum/GL/Buffer.cpp | 68 ++--- src/Magnum/GL/BufferTexture.cpp | 12 +- src/Magnum/GL/Context.cpp | 30 ++- src/Magnum/GL/Context.h | 5 +- src/Magnum/GL/CubeMapTexture.cpp | 114 ++++---- src/Magnum/GL/DebugOutput.cpp | 32 +-- src/Magnum/GL/DefaultFramebuffer.cpp | 22 +- src/Magnum/GL/Framebuffer.cpp | 66 ++--- src/Magnum/GL/Implementation/State.cpp | 84 +++++- src/Magnum/GL/Implementation/State.h | 33 +-- .../GL/Implementation/maxTextureSize.cpp | 8 +- src/Magnum/GL/Mesh.cpp | 50 ++-- src/Magnum/GL/MeshView.cpp | 2 +- src/Magnum/GL/RectangleTexture.cpp | 2 +- src/Magnum/GL/Renderbuffer.cpp | 18 +- src/Magnum/GL/Renderer.cpp | 34 +-- src/Magnum/GL/Sampler.cpp | 2 +- src/Magnum/GL/Shader.cpp | 60 ++--- src/Magnum/GL/TransformFeedback.cpp | 28 +- 24 files changed, 583 insertions(+), 523 deletions(-) diff --git a/src/Magnum/GL/AbstractFramebuffer.cpp b/src/Magnum/GL/AbstractFramebuffer.cpp index 659a75881..868f10dc7 100644 --- a/src/Magnum/GL/AbstractFramebuffer.cpp +++ b/src/Magnum/GL/AbstractFramebuffer.cpp @@ -51,7 +51,7 @@ namespace Magnum { namespace GL { Vector2i AbstractFramebuffer::maxViewportSize() { - Vector2i& value = Context::current().state().framebuffer->maxViewportSize; + Vector2i& value = Context::current().state().framebuffer.maxViewportSize; /* Get the value, if not already cached */ if(value == Vector2i()) @@ -72,7 +72,7 @@ Int AbstractFramebuffer::maxDrawBuffers() { #endif #endif - GLint& value = Context::current().state().framebuffer->maxDrawBuffers; + GLint& value = Context::current().state().framebuffer.maxDrawBuffers; /* Get the value, if not already cached */ if(value == 0) { @@ -91,7 +91,7 @@ Int AbstractFramebuffer::maxDualSourceDrawBuffers() { if(!Context::current().isExtensionSupported()) return 0; - GLint& value = Context::current().state().framebuffer->maxDualSourceDrawBuffers; + GLint& value = Context::current().state().framebuffer.maxDualSourceDrawBuffers; /* Get the value, if not already cached */ if(value == 0) @@ -124,13 +124,13 @@ void AbstractFramebuffer::bindInternal(FramebufferTarget target) { static_cast(target); bindImplementationSingle(); #else - (this->*Context::current().state().framebuffer->bindImplementation)(target); + (this->*Context::current().state().framebuffer.bindImplementation)(target); #endif } #ifdef MAGNUM_TARGET_GLES2 void AbstractFramebuffer::bindImplementationSingle(FramebufferTarget) { - Implementation::FramebufferState& state = *Context::current().state().framebuffer; + Implementation::FramebufferState& state = Context::current().state().framebuffer; CORRADE_INTERNAL_ASSERT(state.readBinding == state.drawBinding); if(state.readBinding == _id) return; @@ -146,7 +146,7 @@ void AbstractFramebuffer::bindImplementationSingle(FramebufferTarget) { inline #endif void AbstractFramebuffer::bindImplementationDefault(FramebufferTarget target) { - Implementation::FramebufferState& state = *Context::current().state().framebuffer; + Implementation::FramebufferState& state = Context::current().state().framebuffer; if(target == FramebufferTarget::Read) { if(state.readBinding == _id) return; @@ -167,13 +167,13 @@ FramebufferTarget AbstractFramebuffer::bindInternal() { #elif defined(MAGNUM_TARGET_WEBGL) return bindImplementationSingle(); #else - return (this->*Context::current().state().framebuffer->bindInternalImplementation)(); + return (this->*Context::current().state().framebuffer.bindInternalImplementation)(); #endif } #ifdef MAGNUM_TARGET_GLES2 FramebufferTarget AbstractFramebuffer::bindImplementationSingle() { - Implementation::FramebufferState& state = *Context::current().state().framebuffer; + Implementation::FramebufferState& state = Context::current().state().framebuffer; CORRADE_INTERNAL_ASSERT(state.readBinding == state.drawBinding); /* Bind the framebuffer, if not already */ @@ -197,7 +197,7 @@ FramebufferTarget AbstractFramebuffer::bindImplementationSingle() { inline #endif FramebufferTarget AbstractFramebuffer::bindImplementationDefault() { - Implementation::FramebufferState& state = *Context::current().state().framebuffer; + Implementation::FramebufferState& state = Context::current().state().framebuffer; /* Return target to which the framebuffer is already bound */ if(state.readBinding == _id) @@ -215,11 +215,11 @@ FramebufferTarget AbstractFramebuffer::bindImplementationDefault() { } PixelFormat AbstractFramebuffer::implementationColorReadFormat() { - return PixelFormat((this->*Context::current().state().framebuffer->implementationColorReadFormatTypeImplementation)(GL_IMPLEMENTATION_COLOR_READ_FORMAT)); + return PixelFormat((this->*Context::current().state().framebuffer.implementationColorReadFormatTypeImplementation)(GL_IMPLEMENTATION_COLOR_READ_FORMAT)); } PixelType AbstractFramebuffer::implementationColorReadType() { - return PixelType((this->*Context::current().state().framebuffer->implementationColorReadFormatTypeImplementation)(GL_IMPLEMENTATION_COLOR_READ_TYPE)); + return PixelType((this->*Context::current().state().framebuffer.implementationColorReadFormatTypeImplementation)(GL_IMPLEMENTATION_COLOR_READ_TYPE)); } GLenum AbstractFramebuffer::implementationColorReadFormatTypeImplementationGlobal(const GLenum what) { @@ -254,7 +254,7 @@ GLenum AbstractFramebuffer::implementationColorReadFormatTypeImplementationFrame #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Range2Di& sourceRectangle, const Range2Di& destinationRectangle, const FramebufferBlitMask mask, const FramebufferBlitFilter filter) { - Context::current().state().framebuffer->blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter); + Context::current().state().framebuffer.blitImplementation(source, destination, sourceRectangle, destinationRectangle, mask, filter); } #endif @@ -290,14 +290,14 @@ AbstractFramebuffer& AbstractFramebuffer::setViewport(const Range2Di& rectangle) _viewport = rectangle; /* Update the viewport if the framebuffer is currently bound */ - if(Context::current().state().framebuffer->drawBinding == _id) + if(Context::current().state().framebuffer.drawBinding == _id) setViewportInternal(); return *this; } void AbstractFramebuffer::setViewportInternal() { - Implementation::FramebufferState& state = *Context::current().state().framebuffer; + Implementation::FramebufferState& state = Context::current().state().framebuffer; CORRADE_INTERNAL_ASSERT(_viewport != Implementation::FramebufferState::DisengagedViewport); CORRADE_INTERNAL_ASSERT(state.drawBinding == _id); @@ -320,17 +320,17 @@ AbstractFramebuffer& AbstractFramebuffer::clear(const FramebufferClearMask mask) #ifndef MAGNUM_TARGET_GLES2 AbstractFramebuffer& AbstractFramebuffer::clearDepth(const Float depth) { - (this->*Context::current().state().framebuffer->clearFImplementation)(GL_DEPTH, 0, &depth); + (this->*Context::current().state().framebuffer.clearFImplementation)(GL_DEPTH, 0, &depth); return *this; } AbstractFramebuffer& AbstractFramebuffer::clearStencil(const Int stencil) { - (this->*Context::current().state().framebuffer->clearIImplementation)(GL_STENCIL, 0, &stencil); + (this->*Context::current().state().framebuffer.clearIImplementation)(GL_STENCIL, 0, &stencil); return *this; } AbstractFramebuffer& AbstractFramebuffer::clearDepthStencil(const Float depth, const Int stencil) { - (this->*Context::current().state().framebuffer->clearFIImplementation)(GL_DEPTH_STENCIL, depth, stencil); + (this->*Context::current().state().framebuffer.clearFIImplementation)(GL_DEPTH_STENCIL, depth, stencil); return *this; } #endif @@ -345,8 +345,8 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, const MutableImageView #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelPack); #endif - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (Context::current().state().framebuffer->readImplementation)(rectangle, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data() + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (Context::current().state().framebuffer.readImplementation)(rectangle, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffsetFor(image, rectangle.size()) #endif @@ -382,8 +382,8 @@ void AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D& image, image.setData(image.storage(), image.format(), image.type(), rectangle.size(), nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (Context::current().state().framebuffer->readImplementation)(rectangle, image.format(), image.type(), dataSize, nullptr); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (Context::current().state().framebuffer.readImplementation)(rectangle, image.format(), image.type(), dataSize, nullptr); } BufferImage2D AbstractFramebuffer::read(const Range2Di& rectangle, BufferImage2D&& image, BufferUsage usage) { @@ -433,52 +433,52 @@ void AbstractFramebuffer::copyImage(const Range2Di& rectangle, Texture1DArray& t void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1D& texture, const Int level, const Int offset) { CORRADE_ASSERT(rectangle.sizeY() == 1, "GL::AbstractFramebuffer::copyImage(): height must be 1 for 1D textures", ); bindInternal(FramebufferTarget::Read); - Context::current().state().framebuffer->copySub1DImplementation(rectangle, texture, level, offset); + Context::current().state().framebuffer.copySub1DImplementation(rectangle, texture, level, offset); } #endif void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2D& texture, const Int level, const Vector2i& offset) { bindInternal(FramebufferTarget::Read); - Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_2D, level, offset); + Context::current().state().framebuffer.copySub2DImplementation(rectangle, texture, GL_TEXTURE_2D, level, offset); } #ifndef MAGNUM_TARGET_GLES void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, RectangleTexture& texture, const Vector2i& offset) { bindInternal(FramebufferTarget::Read); - Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_RECTANGLE, 0, offset); + Context::current().state().framebuffer.copySub2DImplementation(rectangle, texture, GL_TEXTURE_RECTANGLE, 0, offset); } #endif void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTexture& texture, const Int level, const Vector3i& offset) { bindInternal(FramebufferTarget::Read); - Context::current().state().framebuffer->copySubCubeMapImplementation(rectangle, texture, GL_TEXTURE_CUBE_MAP_POSITIVE_X + offset.z(), level, offset.xy()); + Context::current().state().framebuffer.copySubCubeMapImplementation(rectangle, texture, GL_TEXTURE_CUBE_MAP_POSITIVE_X + offset.z(), level, offset.xy()); } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture3D& texture, const Int level, const Vector3i& offset) { bindInternal(FramebufferTarget::Read); - Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); + Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset); } #endif #ifndef MAGNUM_TARGET_GLES void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture1DArray& texture, const Int level, const Vector2i& offset) { bindInternal(FramebufferTarget::Read); - Context::current().state().framebuffer->copySub2DImplementation(rectangle, texture, GL_TEXTURE_1D_ARRAY, level, offset); + Context::current().state().framebuffer.copySub2DImplementation(rectangle, texture, GL_TEXTURE_1D_ARRAY, level, offset); } #endif #ifndef MAGNUM_TARGET_GLES2 void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, Texture2DArray& texture, const Int level, const Vector3i& offset) { bindInternal(FramebufferTarget::Read); - Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); + Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset); } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void AbstractFramebuffer::copySubImage(const Range2Di& rectangle, CubeMapTextureArray& texture, const Int level, const Vector3i& offset) { bindInternal(FramebufferTarget::Read); - Context::current().state().framebuffer->copySub3DImplementation(rectangle, texture, level, offset); + Context::current().state().framebuffer.copySub3DImplementation(rectangle, texture, level, offset); } #endif diff --git a/src/Magnum/GL/AbstractObject.cpp b/src/Magnum/GL/AbstractObject.cpp index 616e5eade..965246eee 100644 --- a/src/Magnum/GL/AbstractObject.cpp +++ b/src/Magnum/GL/AbstractObject.cpp @@ -110,7 +110,7 @@ Int AbstractObject::maxLabelLength() { if(!Context::current().isExtensionSupported()) return 0; - GLint& value = Context::current().state().debug->maxLabelLength; + GLint& value = Context::current().state().debug.maxLabelLength; if(value == 0) { #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/Magnum/GL/AbstractQuery.cpp b/src/Magnum/GL/AbstractQuery.cpp index c0e596223..095ce0a7f 100644 --- a/src/Magnum/GL/AbstractQuery.cpp +++ b/src/Magnum/GL/AbstractQuery.cpp @@ -37,7 +37,7 @@ namespace Magnum { namespace GL { AbstractQuery::AbstractQuery(GLenum target): _target{target}, _flags{ObjectFlag::DeleteOnDestruction} { - (this->*Context::current().state().query->createImplementation)(); + (this->*Context::current().state().query.createImplementation)(); } AbstractQuery::~AbstractQuery() { @@ -93,17 +93,17 @@ void AbstractQuery::createImplementationDSAExceptPipelineStats() { #ifndef MAGNUM_TARGET_WEBGL std::string AbstractQuery::label() const { #ifndef MAGNUM_TARGET_GLES2 - return Context::current().state().debug->getLabelImplementation(GL_QUERY, _id); + return Context::current().state().debug.getLabelImplementation(GL_QUERY, _id); #else - return Context::current().state().debug->getLabelImplementation(GL_QUERY_KHR, _id); + return Context::current().state().debug.getLabelImplementation(GL_QUERY_KHR, _id); #endif } AbstractQuery& AbstractQuery::setLabelInternal(const Containers::ArrayView label) { #ifndef MAGNUM_TARGET_GLES2 - Context::current().state().debug->labelImplementation(GL_QUERY, _id, label); + Context::current().state().debug.labelImplementation(GL_QUERY, _id, label); #else - Context::current().state().debug->labelImplementation(GL_QUERY_KHR, _id, label); + Context::current().state().debug.labelImplementation(GL_QUERY_KHR, _id, label); #endif return *this; } diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index 065fc7dad..44ab50947 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -47,7 +47,7 @@ namespace Magnum { namespace GL { Int AbstractShaderProgram::maxVertexAttributes() { - GLint& value = Context::current().state().shaderProgram->maxVertexAttributes; + GLint& value = Context::current().state().shaderProgram.maxVertexAttributes; /* Get the value, if not already cached */ if(value == 0) @@ -66,7 +66,7 @@ Int AbstractShaderProgram::maxGeometryOutputVertices() { return 0; #endif - GLint& value = Context::current().state().shaderProgram->maxGeometryOutputVertices; + GLint& value = Context::current().state().shaderProgram.maxGeometryOutputVertices; if(value == 0) glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &value); @@ -82,7 +82,7 @@ Int AbstractShaderProgram::maxAtomicCounterBufferSize() { #endif return 0; - GLint& value = Context::current().state().shaderProgram->maxAtomicCounterBufferSize; + GLint& value = Context::current().state().shaderProgram.maxAtomicCounterBufferSize; if(value == 0) glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, &value); @@ -98,7 +98,7 @@ Int AbstractShaderProgram::maxComputeSharedMemorySize() { #endif return 0; - GLint& value = Context::current().state().shaderProgram->maxComputeSharedMemorySize; + GLint& value = Context::current().state().shaderProgram.maxComputeSharedMemorySize; if(value == 0) glGetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &value); @@ -114,7 +114,7 @@ Int AbstractShaderProgram::maxComputeWorkGroupInvocations() { #endif return 0; - GLint& value = Context::current().state().shaderProgram->maxComputeWorkGroupInvocations; + GLint& value = Context::current().state().shaderProgram.maxComputeWorkGroupInvocations; if(value == 0) glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &value); @@ -130,7 +130,7 @@ Vector3i AbstractShaderProgram::maxComputeWorkGroupCount() { #endif return {}; - Vector3i& value = Context::current().state().shaderProgram->maxComputeWorkGroupCount; + Vector3i& value = Context::current().state().shaderProgram.maxComputeWorkGroupCount; if(value.isZero()) { glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &value.x()); @@ -149,7 +149,7 @@ Vector3i AbstractShaderProgram::maxComputeWorkGroupSize() { #endif return {}; - Vector3i& value = Context::current().state().shaderProgram->maxComputeWorkGroupSize; + Vector3i& value = Context::current().state().shaderProgram.maxComputeWorkGroupSize; if(value.isZero()) { glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &value.x()); @@ -168,7 +168,7 @@ Int AbstractShaderProgram::maxImageUnits() { #endif return 0; - GLint& value = Context::current().state().shaderProgram->maxImageUnits; + GLint& value = Context::current().state().shaderProgram.maxImageUnits; if(value == 0) glGetIntegerv(GL_MAX_IMAGE_UNITS, &value); @@ -182,7 +182,7 @@ Int AbstractShaderProgram::maxImageSamples() { if(!Context::current().isExtensionSupported()) return 0; - GLint& value = Context::current().state().shaderProgram->maxImageSamples; + GLint& value = Context::current().state().shaderProgram.maxImageSamples; if(value == 0) glGetIntegerv(GL_MAX_IMAGE_SAMPLES, &value); @@ -201,7 +201,7 @@ Int AbstractShaderProgram::maxCombinedShaderOutputResources() { #endif return 0; - GLint& value = Context::current().state().shaderProgram->maxCombinedShaderOutputResources; + GLint& value = Context::current().state().shaderProgram.maxCombinedShaderOutputResources; if(value == 0) glGetIntegerv(GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES, &value); @@ -217,7 +217,7 @@ Long AbstractShaderProgram::maxShaderStorageBlockSize() { #endif return 0; - GLint64& value = Context::current().state().shaderProgram->maxShaderStorageBlockSize; + GLint64& value = Context::current().state().shaderProgram.maxShaderStorageBlockSize; if(value == 0) glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &value); @@ -232,7 +232,7 @@ Int AbstractShaderProgram::maxUniformBlockSize() { return 0; #endif - GLint& value = Context::current().state().shaderProgram->maxUniformBlockSize; + GLint& value = Context::current().state().shaderProgram.maxUniformBlockSize; if(value == 0) glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &value); @@ -249,7 +249,7 @@ Int AbstractShaderProgram::maxUniformLocations() { #endif return 0; - GLint& value = Context::current().state().shaderProgram->maxUniformLocations; + GLint& value = Context::current().state().shaderProgram.maxUniformLocations; if(value == 0) glGetIntegerv(GL_MAX_UNIFORM_LOCATIONS, &value); @@ -264,7 +264,7 @@ Int AbstractShaderProgram::minTexelOffset() { return 0; #endif - GLint& value = Context::current().state().shaderProgram->minTexelOffset; + GLint& value = Context::current().state().shaderProgram.minTexelOffset; if(value == 0) glGetIntegerv(GL_MIN_PROGRAM_TEXEL_OFFSET, &value); @@ -278,7 +278,7 @@ Int AbstractShaderProgram::maxTexelOffset() { return 0; #endif - GLint& value = Context::current().state().shaderProgram->maxTexelOffset; + GLint& value = Context::current().state().shaderProgram.maxTexelOffset; if(value == 0) glGetIntegerv(GL_MAX_PROGRAM_TEXEL_OFFSET, &value); @@ -301,7 +301,7 @@ AbstractShaderProgram::~AbstractShaderProgram() { if(!_id) return; /* Remove current usage from the state */ - GLuint& current = Context::current().state().shaderProgram->current; + GLuint& current = Context::current().state().shaderProgram.current; if(current == _id) current = 0; glDeleteProgram(_id); @@ -316,17 +316,17 @@ AbstractShaderProgram& AbstractShaderProgram::operator=(AbstractShaderProgram&& #ifndef MAGNUM_TARGET_WEBGL std::string AbstractShaderProgram::label() const { #ifndef MAGNUM_TARGET_GLES2 - return Context::current().state().debug->getLabelImplementation(GL_PROGRAM, _id); + return Context::current().state().debug.getLabelImplementation(GL_PROGRAM, _id); #else - return Context::current().state().debug->getLabelImplementation(GL_PROGRAM_KHR, _id); + return Context::current().state().debug.getLabelImplementation(GL_PROGRAM_KHR, _id); #endif } AbstractShaderProgram& AbstractShaderProgram::setLabelInternal(const Containers::ArrayView label) { #ifndef MAGNUM_TARGET_GLES2 - Context::current().state().debug->labelImplementation(GL_PROGRAM, _id, label); + Context::current().state().debug.labelImplementation(GL_PROGRAM, _id, label); #else - Context::current().state().debug->labelImplementation(GL_PROGRAM_KHR, _id, label); + Context::current().state().debug.labelImplementation(GL_PROGRAM_KHR, _id, label); #endif return *this; } @@ -394,7 +394,7 @@ void AbstractShaderProgram::draw(Containers::ArrayViewmultiDrawImplementation(meshes); + Context::current().state().mesh.multiDrawImplementation(meshes); #endif } @@ -429,7 +429,7 @@ void AbstractShaderProgram::dispatchCompute(const Vector3ui& workgroupCount) { void AbstractShaderProgram::use() { /* Use only if the program isn't already in use */ - GLuint& current = Context::current().state().shaderProgram->current; + GLuint& current = Context::current().state().shaderProgram.current; if(current != _id) glUseProgram(current = _id); } @@ -456,7 +456,7 @@ void AbstractShaderProgram::bindFragmentDataLocationIndexedInternal(const Unsign #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgram::setTransformFeedbackOutputs(const std::initializer_list outputs, const TransformFeedbackBufferMode bufferMode) { - (this->*Context::current().state().shaderProgram->transformFeedbackVaryingsImplementation)({outputs.begin(), outputs.size()}, bufferMode); + (this->*Context::current().state().shaderProgram.transformFeedbackVaryingsImplementation)({outputs.begin(), outputs.size()}, bufferMode); } void AbstractShaderProgram::transformFeedbackVaryingsImplementationDefault(const Containers::ArrayView outputs, const TransformFeedbackBufferMode bufferMode) { @@ -507,7 +507,7 @@ bool AbstractShaderProgram::link(std::initializer_listcleanLogImplementation(message); + Context::current().state().shaderProgram.cleanLogImplementation(message); /* Show error log */ if(!success) { @@ -563,7 +563,7 @@ UnsignedInt AbstractShaderProgram::uniformBlockIndexInternal(const Containers::A #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - (this->*Context::current().state().shaderProgram->uniform1fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform1fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLfloat* const values) { @@ -584,7 +584,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform2fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform2fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) { @@ -605,7 +605,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform3fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform3fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) { @@ -626,7 +626,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform4fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform4fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) { @@ -647,7 +647,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - (this->*Context::current().state().shaderProgram->uniform1ivImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform1ivImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLint* values) { @@ -668,7 +668,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform2ivImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform2ivImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) { @@ -689,7 +689,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform3ivImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform3ivImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) { @@ -710,7 +710,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform4ivImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform4ivImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) { @@ -732,7 +732,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - (this->*Context::current().state().shaderProgram->uniform1uivImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform1uivImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLuint* const values) { @@ -753,7 +753,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform2uivImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform2uivImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) { @@ -774,7 +774,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform3uivImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform3uivImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) { @@ -795,7 +795,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform4uivImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform4uivImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) { @@ -818,7 +818,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - (this->*Context::current().state().shaderProgram->uniform1dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform1dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLdouble* const values) { @@ -831,7 +831,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform2dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform2dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) { @@ -844,7 +844,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform3dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform3dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) { @@ -857,7 +857,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniform4dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniform4dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) { @@ -871,7 +871,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix2fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix2fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) { @@ -892,7 +892,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix3fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix3fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) { @@ -913,7 +913,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix4fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix4fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) { @@ -935,7 +935,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix2x3fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix2x3fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) { @@ -956,7 +956,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix3x2fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix3x2fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) { @@ -977,7 +977,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix2x4fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix2x4fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) { @@ -998,7 +998,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix4x2fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix4x2fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) { @@ -1019,7 +1019,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix3x4fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix3x4fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) { @@ -1040,7 +1040,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix4x3fvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix4x3fvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) { @@ -1063,7 +1063,7 @@ void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, co #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix2dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix2dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) { @@ -1076,7 +1076,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix3dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix3dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) { @@ -1089,7 +1089,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix4dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix4dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) { @@ -1102,7 +1102,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix2x3dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix2x3dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) { @@ -1115,7 +1115,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix3x2dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix3x2dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) { @@ -1128,7 +1128,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix2x4dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix2x4dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) { @@ -1141,7 +1141,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix4x2dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix4x2dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) { @@ -1154,7 +1154,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix3x4dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix3x4dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) { @@ -1167,7 +1167,7 @@ void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram->uniformMatrix4x3dvImplementation)(location, values.size(), values); + (this->*Context::current().state().shaderProgram.uniformMatrix4x3dvImplementation)(location, values.size(), values); } void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) { diff --git a/src/Magnum/GL/AbstractTexture.cpp b/src/Magnum/GL/AbstractTexture.cpp index 29cdd3dd9..4efa513ae 100644 --- a/src/Magnum/GL/AbstractTexture.cpp +++ b/src/Magnum/GL/AbstractTexture.cpp @@ -51,7 +51,7 @@ namespace Magnum { namespace GL { #ifndef MAGNUM_TARGET_GLES2 Float AbstractTexture::maxLodBias() { - GLfloat& value = Context::current().state().texture->maxLodBias; + GLfloat& value = Context::current().state().texture.maxLodBias; /* Get the value, if not already cached */ if(value == 0.0f) @@ -70,7 +70,7 @@ Int AbstractTexture::maxColorSamples() { #endif return 0; - GLint& value = Context::current().state().texture->maxColorSamples; + GLint& value = Context::current().state().texture.maxColorSamples; /* Get the value, if not already cached */ if(value == 0) @@ -87,7 +87,7 @@ Int AbstractTexture::maxDepthSamples() { #endif return 0; - GLint& value = Context::current().state().texture->maxDepthSamples; + GLint& value = Context::current().state().texture.maxDepthSamples; /* Get the value, if not already cached */ if(value == 0) @@ -104,7 +104,7 @@ Int AbstractTexture::maxIntegerSamples() { #endif return 0; - GLint& value = Context::current().state().texture->maxIntegerSamples; + GLint& value = Context::current().state().texture.maxIntegerSamples; /* Get the value, if not already cached */ if(value == 0) @@ -115,20 +115,20 @@ Int AbstractTexture::maxIntegerSamples() { #endif void AbstractTexture::unbind(const Int textureUnit) { - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; /* If given texture unit is already unbound, nothing to do */ if(textureState.bindings[textureUnit].second == 0) return; /* Unbind the texture, reset state tracker */ - Context::current().state().texture->unbindImplementation(textureUnit); + Context::current().state().texture.unbindImplementation(textureUnit); /* libstdc++ since GCC 6.3 can't handle just = {} (ambiguous overload of operator=) */ textureState.bindings[textureUnit] = std::pair{}; } void AbstractTexture::unbindImplementationDefault(const GLint textureUnit) { - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; /* Activate given texture unit if not already active, update state tracker */ if(textureState.currentTextureUnit != textureUnit) @@ -145,20 +145,20 @@ void AbstractTexture::unbindImplementationMulti(const GLint textureUnit) { } void AbstractTexture::unbindImplementationDSA(const GLint textureUnit) { - CORRADE_INTERNAL_ASSERT(Context::current().state().texture->bindings[textureUnit].first != 0); + CORRADE_INTERNAL_ASSERT(Context::current().state().texture.bindings[textureUnit].first != 0); glBindTextureUnit(textureUnit, 0); } #endif void AbstractTexture::unbind(const Int firstTextureUnit, const std::size_t count) { /* State tracker is updated in the implementations */ - Context::current().state().texture->bindMultiImplementation(firstTextureUnit, {nullptr, count}); + Context::current().state().texture.bindMultiImplementation(firstTextureUnit, {nullptr, count}); } /** @todoc const std::initializer_list makes Doxygen grumpy */ void AbstractTexture::bind(const Int firstTextureUnit, Containers::ArrayView textures) { /* State tracker is updated in the implementations */ - Context::current().state().texture->bindMultiImplementation(firstTextureUnit, {textures.begin(), textures.size()}); + Context::current().state().texture.bindMultiImplementation(firstTextureUnit, {textures.begin(), textures.size()}); } void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, const Containers::ArrayView textures) { @@ -169,7 +169,7 @@ void AbstractTexture::bindImplementationFallback(const GLint firstTextureUnit, c #ifndef MAGNUM_TARGET_GLES /** @todoc const Containers::ArrayView makes Doxygen grumpy */ void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, Containers::ArrayView textures) { - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; /* Create array of IDs and also update bindings in state tracker */ /** @todo VLAs */ @@ -196,7 +196,7 @@ void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, Cont #ifndef MAGNUM_TARGET_GLES Int AbstractTexture::compressedBlockDataSize(const GLenum target, const TextureFormat format) { - return (Context::current().state().texture->compressedBlockDataSizeImplementation)(target, format); + return (Context::current().state().texture.compressedBlockDataSizeImplementation)(target, format); } Int AbstractTexture::compressedBlockDataSizeImplementationDefault(const GLenum target, const TextureFormat format) { @@ -212,7 +212,7 @@ Int AbstractTexture::compressedBlockDataSizeImplementationBitsWorkaround(const G #endif AbstractTexture::AbstractTexture(GLenum target): _target{target}, _flags{ObjectFlag::DeleteOnDestruction} { - (this->*Context::current().state().texture->createImplementation)(); + (this->*Context::current().state().texture.createImplementation)(); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } @@ -232,7 +232,7 @@ AbstractTexture::~AbstractTexture() { if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; /* Remove all bindings */ - for(auto& binding: Context::current().state().texture->bindings) { + for(auto& binding: Context::current().state().texture.bindings) { /* MSVC 2015 needs the parentheses around */ /* libstdc++ since GCC 6.3 can't handle just = {} (ambiguous overload of operator=) */ @@ -241,7 +241,7 @@ AbstractTexture::~AbstractTexture() { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) /* Remove all image bindings */ - for(auto& binding: Context::current().state().texture->imageBindings) { + for(auto& binding: Context::current().state().texture.imageBindings) { /* MSVC 2015 needs the parentheses around */ if(std::get<0>(binding) == _id) binding = {}; } @@ -264,19 +264,19 @@ void AbstractTexture::createIfNotAlready() { #ifndef MAGNUM_TARGET_WEBGL std::string AbstractTexture::label() { createIfNotAlready(); - return Context::current().state().debug->getLabelImplementation(GL_TEXTURE, _id); + return Context::current().state().debug.getLabelImplementation(GL_TEXTURE, _id); } AbstractTexture& AbstractTexture::setLabelInternal(const Containers::ArrayView label) { createIfNotAlready(); - Context::current().state().debug->labelImplementation(GL_TEXTURE, _id, label); + Context::current().state().debug.labelImplementation(GL_TEXTURE, _id, label); return *this; } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void AbstractTexture::unbindImage(const Int imageUnit) { - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; /* If already unbound in given image unit, nothing to do */ if(std::get<0>(textureState.imageBindings[imageUnit]) == 0) return; @@ -289,7 +289,7 @@ void AbstractTexture::unbindImage(const Int imageUnit) { #ifndef MAGNUM_TARGET_GLES /** @todoc const Containers::ArrayView makes Doxygen grumpy */ void AbstractTexture::bindImages(const Int firstImageUnit, Containers::ArrayView textures) { - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; /* Create array of IDs and also update bindings in state tracker */ Containers::Array ids{textures ? textures.size() : 0}; @@ -318,7 +318,7 @@ void AbstractTexture::bindImages(const Int firstImageUnit, Containers::ArrayView #endif void AbstractTexture::bindImageInternal(const Int imageUnit, const Int level, const bool layered, const Int layer, const ImageAccess access, const ImageFormat format) { - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; const std::tuple state{_id, level, layered, layer, GLenum(access)}; /* If already bound in given texture unit, nothing to do */ @@ -331,7 +331,7 @@ void AbstractTexture::bindImageInternal(const Int imageUnit, const Int level, co #endif void AbstractTexture::bind(Int textureUnit) { - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; /* If already bound in given texture unit, nothing to do */ if(textureState.bindings[textureUnit].second == _id) return; @@ -342,7 +342,7 @@ void AbstractTexture::bind(Int textureUnit) { } void AbstractTexture::bindImplementationDefault(GLint textureUnit) { - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; /* Activate given texture unit if not already active, update state tracker */ if(textureState.currentTextureUnit != textureUnit) @@ -375,20 +375,20 @@ void AbstractTexture::bindImplementationDSAIntelWindows(const GLint textureUnit) void AbstractTexture::bindImplementationAppleBufferTextureWorkaround(const GLint textureUnit) { bindImplementationDefault(textureUnit); if(_target == GL_TEXTURE_BUFFER) - Context::current().state().texture->bufferTextureBound.set(textureUnit, true); + Context::current().state().texture.bufferTextureBound.set(textureUnit, true); } #endif #endif #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::setBaseLevel(Int level) { - (this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_BASE_LEVEL, level); + (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_BASE_LEVEL, level); } #endif #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void AbstractTexture::setMaxLevel(Int level) { - (this->*Context::current().state().texture->parameteriImplementation)( + (this->*Context::current().state().texture.parameteriImplementation)( #ifndef MAGNUM_TARGET_GLES2 GL_TEXTURE_MAX_LEVEL #else @@ -399,32 +399,32 @@ void AbstractTexture::setMaxLevel(Int level) { #endif void AbstractTexture::setMinificationFilter(SamplerFilter filter, SamplerMipmap mipmap) { - (this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap)); + (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_MIN_FILTER, GLint(filter)|GLint(mipmap)); } void AbstractTexture::setMagnificationFilter(const SamplerFilter filter) { - (this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter)); + (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_MAG_FILTER, GLint(filter)); } #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::setMinLod(const Float lod) { - (this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_MIN_LOD, lod); + (this->*Context::current().state().texture.parameterfImplementation)(GL_TEXTURE_MIN_LOD, lod); } void AbstractTexture::setMaxLod(const Float lod) { - (this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_MAX_LOD, lod); + (this->*Context::current().state().texture.parameterfImplementation)(GL_TEXTURE_MAX_LOD, lod); } #endif #ifndef MAGNUM_TARGET_GLES void AbstractTexture::setLodBias(const Float bias) { - (this->*Context::current().state().texture->parameterfImplementation)(GL_TEXTURE_LOD_BIAS, bias); + (this->*Context::current().state().texture.parameterfImplementation)(GL_TEXTURE_LOD_BIAS, bias); } #endif #ifndef MAGNUM_TARGET_WEBGL void AbstractTexture::setBorderColor(const Color4& color) { - (this->*Context::current().state().texture->parameterfvImplementation)( + (this->*Context::current().state().texture.parameterfvImplementation)( #ifndef MAGNUM_TARGET_GLES2 GL_TEXTURE_BORDER_COLOR, #else @@ -435,22 +435,22 @@ void AbstractTexture::setBorderColor(const Color4& color) { #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::setBorderColor(const Vector4ui& color) { - (this->*Context::current().state().texture->parameterIuivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); + (this->*Context::current().state().texture.parameterIuivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); } void AbstractTexture::setBorderColor(const Vector4i& color) { - (this->*Context::current().state().texture->parameterIivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); + (this->*Context::current().state().texture.parameterIivImplementation)(GL_TEXTURE_BORDER_COLOR, color.data()); } #endif #endif void AbstractTexture::setMaxAnisotropy(const Float anisotropy) { - (this->*Context::current().state().texture->setMaxAnisotropyImplementation)(anisotropy); + (this->*Context::current().state().texture.setMaxAnisotropyImplementation)(anisotropy); } #ifndef MAGNUM_TARGET_WEBGL void AbstractTexture::setSrgbDecode(bool decode) { - (this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SRGB_DECODE_EXT, + (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SRGB_DECODE_EXT, decode ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT); } #endif @@ -459,19 +459,19 @@ void AbstractTexture::setSrgbDecode(bool decode) { void AbstractTexture::setSwizzleInternal(const GLint r, const GLint g, const GLint b, const GLint a) { #ifndef MAGNUM_TARGET_GLES const GLint rgba[] = {r, g, b, a}; - (this->*Context::current().state().texture->parameterivImplementation)(GL_TEXTURE_SWIZZLE_RGBA, rgba); + (this->*Context::current().state().texture.parameterivImplementation)(GL_TEXTURE_SWIZZLE_RGBA, rgba); #else - (this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_R, r); - (this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_G, g); - (this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_B, b); - (this->*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_SWIZZLE_A, a); + (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_R, r); + (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_G, g); + (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_B, b); + (this->*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_SWIZZLE_A, a); #endif } #endif #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void AbstractTexture::setCompareMode(const SamplerCompareMode mode) { - (this->*Context::current().state().texture->parameteriImplementation)( + (this->*Context::current().state().texture.parameteriImplementation)( #ifndef MAGNUM_TARGET_GLES2 GL_TEXTURE_COMPARE_MODE #else @@ -481,7 +481,7 @@ void AbstractTexture::setCompareMode(const SamplerCompareMode mode) { } void AbstractTexture::setCompareFunction(const SamplerCompareFunction function) { - (this->*Context::current().state().texture->parameteriImplementation)( + (this->*Context::current().state().texture.parameteriImplementation)( #ifndef MAGNUM_TARGET_GLES2 GL_TEXTURE_COMPARE_FUNC #else @@ -493,16 +493,16 @@ void AbstractTexture::setCompareFunction(const SamplerCompareFunction function) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void AbstractTexture::setDepthStencilMode(const SamplerDepthStencilMode mode) { - (this->*Context::current().state().texture->parameteriImplementation)(GL_DEPTH_STENCIL_TEXTURE_MODE, GLenum(mode)); + (this->*Context::current().state().texture.parameteriImplementation)(GL_DEPTH_STENCIL_TEXTURE_MODE, GLenum(mode)); } #endif void AbstractTexture::invalidateImage(const Int level) { - (this->*Context::current().state().texture->invalidateImageImplementation)(level); + (this->*Context::current().state().texture.invalidateImageImplementation)(level); } void AbstractTexture::generateMipmap() { - (this->*Context::current().state().texture->mipmapImplementation)(); + (this->*Context::current().state().texture.mipmapImplementation)(); } void AbstractTexture::mipmapImplementationDefault() { @@ -521,7 +521,7 @@ void AbstractTexture::bindInternal() { functions need to have the texture bound in *currently active* unit, so we would need to call glActiveTexture() afterwards anyway. */ - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; /* If the texture is already bound in current unit, nothing to do */ if(textureState.bindings[textureState.currentTextureUnit].second == _id) @@ -1281,7 +1281,7 @@ void AbstractTexture::parameterIImplementationDSA(const GLenum parameter, const void AbstractTexture::setMaxAnisotropyImplementationNoOp(GLfloat) {} void AbstractTexture::setMaxAnisotropyImplementationArbOrExt(GLfloat anisotropy) { - (this->*Context::current().state().texture->parameterfImplementation)( + (this->*Context::current().state().texture.parameterfImplementation)( #ifndef MAGNUM_TARGET_GLES GL_TEXTURE_MAX_ANISOTROPY #else @@ -1729,8 +1729,8 @@ template void AbstractTexture::image(GLint level, Image< data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data); image = Image{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)}; } @@ -1748,8 +1748,8 @@ template void AbstractTexture::image(GLint level, const #endif Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getImageImplementation)(level, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()); } template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, const BasicMutableImageView<1>&); @@ -1767,8 +1767,8 @@ template void AbstractTexture::image(GLint level, Buffer image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getImageImplementation)(level, image.format(), image.type(), dataSize, nullptr); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getImageImplementation)(level, image.format(), image.type(), dataSize, nullptr); } template void MAGNUM_GL_EXPORT AbstractTexture::image<1>(GLint, BufferImage<1>&, BufferUsage); @@ -1783,13 +1783,13 @@ template void AbstractTexture::compressedImage(const GLi std::size_t dataSize; if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) { GLint textureDataSize; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); dataSize = textureDataSize; } else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Reallocate only if needed */ Containers::Array data{image.release()}; @@ -1797,8 +1797,8 @@ template void AbstractTexture::compressedImage(const GLi data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCompressedImageImplementation)(level, data.size(), data); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCompressedImageImplementation)(level, data.size(), data); image = CompressedImage{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; } @@ -1820,7 +1820,7 @@ template void AbstractTexture::compressedImage(const GLi std::size_t dataSize; if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) { GLint textureDataSize; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); dataSize = textureDataSize; } else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); @@ -1829,15 +1829,15 @@ template void AbstractTexture::compressedImage(const GLi /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), "GL::AbstractTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); #endif Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCompressedImageImplementation)(level, image.data().size(), image.data()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCompressedImageImplementation)(level, image.data().size(), image.data()); } template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<1>(GLint, const BasicMutableCompressedImageView<1>&); @@ -1852,13 +1852,13 @@ template void AbstractTexture::compressedImage(const GLi std::size_t dataSize; if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) { GLint textureDataSize; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &textureDataSize); dataSize = textureDataSize; } else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Reallocate only if needed */ if(image.dataSize() < dataSize) @@ -1867,8 +1867,8 @@ template void AbstractTexture::compressedImage(const GLi image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCompressedImageImplementation)(level, dataSize, nullptr); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCompressedImageImplementation)(level, dataSize, nullptr); } template void MAGNUM_GL_EXPORT AbstractTexture::compressedImage<1>(GLint, CompressedBufferImage<1>&, BufferUsage); @@ -1904,7 +1904,7 @@ template void AbstractTexture::subImage(const GLint leve const Vector3i paddedSize = Vector3i::pad(size, 1); Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), image.data().size(), image.data()); } @@ -1927,7 +1927,7 @@ template void AbstractTexture::subImage(const GLint leve image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); glGetTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), GLenum(image.format()), GLenum(image.type()), dataSize, nullptr); } @@ -1956,7 +1956,7 @@ template void AbstractTexture::compressedSubImage(const /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Calculate compressed subimage size. If the user-provided pixel storage doesn't tell us all properties about the compression, we need to ask GL @@ -1972,7 +1972,7 @@ template void AbstractTexture::compressedSubImage(const data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), data.size(), data); image = CompressedImage{CompressedPixelFormat(format), size, std::move(data)}; } @@ -1994,7 +1994,7 @@ template void AbstractTexture::compressedSubImage(const #ifndef CORRADE_NO_ASSERT /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), "GL::AbstractTexture::compressedSubImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); @@ -2015,7 +2015,7 @@ template void AbstractTexture::compressedSubImage(const const Vector3i paddedSize = Vector3i::pad(size, 1); Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), image.data().size(), image.data()); } @@ -2032,7 +2032,7 @@ template void AbstractTexture::compressedSubImage(const /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Calculate compressed subimage size. If the user-provided pixel storage doesn't tell us all properties about the compression, we need to ask GL @@ -2049,7 +2049,7 @@ template void AbstractTexture::compressedSubImage(const image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); glGetCompressedTextureSubImage(_id, level, paddedOffset.x(), paddedOffset.y(), paddedOffset.z(), paddedSize.x(), paddedSize.y(), paddedSize.z(), dataSize, nullptr); } @@ -2083,14 +2083,14 @@ Vector3i AbstractTexture::DataHelper<3>::compressedBlockSize(const GLenum target #ifndef MAGNUM_TARGET_GLES Math::Vector<1, GLint> AbstractTexture::DataHelper<1>::imageSize(AbstractTexture& texture, const GLint level) { Math::Vector<1, GLint> value; - (texture.*Context::current().state().texture->getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); + (texture.*Context::current().state().texture.getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); return value; } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture& texture, const GLint level) { - const Implementation::TextureState& state = *Context::current().state().texture; + const Implementation::TextureState& state = Context::current().state().texture; Vector2i value; (texture.*state.getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); @@ -2099,7 +2099,7 @@ Vector2i AbstractTexture::DataHelper<2>::imageSize(AbstractTexture& texture, con } Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture& texture, const GLint level) { - const Implementation::TextureState& state = *Context::current().state().texture; + const Implementation::TextureState& state = Context::current().state().texture; Vector3i value; (texture.*state.getLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); @@ -2111,81 +2111,81 @@ Vector3i AbstractTexture::DataHelper<3>::imageSize(AbstractTexture& texture, con #ifndef MAGNUM_TARGET_GLES void AbstractTexture::DataHelper<1>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Math::Vector< 1, GLsizei >& size) { - (texture.*Context::current().state().texture->storage1DImplementation)(levels, internalFormat, size); + (texture.*Context::current().state().texture.storage1DImplementation)(levels, internalFormat, size); } #endif void AbstractTexture::DataHelper<2>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Vector2i& size) { - (texture.*Context::current().state().texture->storage2DImplementation)(levels, internalFormat, size); + (texture.*Context::current().state().texture.storage2DImplementation)(levels, internalFormat, size); } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void AbstractTexture::DataHelper<3>::setStorage(AbstractTexture& texture, const GLsizei levels, const TextureFormat internalFormat, const Vector3i& size) { - (texture.*Context::current().state().texture->storage3DImplementation)(levels, internalFormat, size); + (texture.*Context::current().state().texture.storage3DImplementation)(levels, internalFormat, size); } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void AbstractTexture::DataHelper<2>::setStorageMultisample(AbstractTexture& texture, const GLsizei samples, const TextureFormat internalFormat, const Vector2i& size, const GLboolean fixedSampleLocations) { - (texture.*Context::current().state().texture->storage2DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations); + (texture.*Context::current().state().texture.storage2DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations); } void AbstractTexture::DataHelper<3>::setStorageMultisample(AbstractTexture& texture, const GLsizei samples, const TextureFormat internalFormat, const Vector3i& size, const GLboolean fixedSampleLocations) { - (texture.*Context::current().state().texture->storage3DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations); + (texture.*Context::current().state().texture.storage3DMultisampleImplementation)(samples, internalFormat, size, fixedSampleLocations); } #endif #ifndef MAGNUM_TARGET_GLES void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, const ImageView1D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(pixelFormat(image.format())), GLenum(pixelType(image.format(), image.formatExtra())), image.data()); } void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, const CompressedImageView1D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); } void AbstractTexture::DataHelper<1>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage1D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glTexImage1D(texture._target, level, GLint(internalFormat), image.size()[0], 0, GLenum(image.format()), GLenum(image.type()), nullptr); } void AbstractTexture::DataHelper<1>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage1D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glCompressedTexImage1D(texture._target, level, GLenum(image.format()), image.size()[0], 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); } void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const ImageView1D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->subImage1DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.subImage1DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data()); } void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const CompressedImageView1D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.compressedSubImage1DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); } void AbstractTexture::DataHelper<1>::setSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, BufferImage1D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->subImage1DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.subImage1DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr); } void AbstractTexture::DataHelper<1>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, CompressedBufferImage1D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.compressedSubImage1DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); } #endif @@ -2193,8 +2193,8 @@ void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GL #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->image2DImplementation)(target, level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.image2DImplementation)(target, level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) #endif @@ -2205,7 +2205,7 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glCompressedTexImage2D(target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); } @@ -2213,14 +2213,14 @@ void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<2>::setImage(AbstractTexture& texture, const GLenum target, const GLint level, const TextureFormat internalFormat, BufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glTexImage2D(target, level, GLint(internalFormat), image.size().x(), image.size().y(), 0, GLenum(image.format()), GLenum(image.type()), nullptr); } void AbstractTexture::DataHelper<2>::setCompressedImage(AbstractTexture& texture, const GLenum target, const GLint level, CompressedBufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glCompressedTexImage2D(target, level, GLenum(image.format()), image.size().x(), image.size().y(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); } @@ -2230,8 +2230,8 @@ void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.subImage2DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) #endif @@ -2242,21 +2242,21 @@ void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& text #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.compressedSubImage2DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); } #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<2>::setSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, BufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.subImage2DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); } void AbstractTexture::DataHelper<2>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, CompressedBufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.compressedSubImage2DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); } #endif @@ -2265,8 +2265,8 @@ void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GL #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->image3DImplementation)(level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.image3DImplementation)(level, internalFormat, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) #endif @@ -2277,7 +2277,7 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); #ifndef MAGNUM_TARGET_GLES2 glCompressedTexImage3D(texture._target, level, GLenum(compressedPixelFormat(image.format())), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); @@ -2290,14 +2290,14 @@ void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<3>::setImage(AbstractTexture& texture, const GLint level, const TextureFormat internalFormat, BufferImage3D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glTexImage3D(texture._target, level, GLint(internalFormat), image.size().x(), image.size().y(), image.size().z(), 0, GLenum(image.format()), GLenum(image.type()), nullptr); } void AbstractTexture::DataHelper<3>::setCompressedImage(AbstractTexture& texture, const GLint level, CompressedBufferImage3D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); texture.bindInternal(); glCompressedTexImage3D(texture._target, level, GLenum(image.format()), image.size().x(), image.size().y(), image.size().z(), 0, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); } @@ -2308,8 +2308,8 @@ void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.subImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) #endif @@ -2320,47 +2320,47 @@ void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& text #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.compressedSubImage3DImplementation)(level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); } #endif #ifndef MAGNUM_TARGET_GLES2 void AbstractTexture::DataHelper<3>::setSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, BufferImage3D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.subImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); } void AbstractTexture::DataHelper<3>::setCompressedSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, CompressedBufferImage3D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (texture.*Context::current().state().texture->compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (texture.*Context::current().state().texture.compressedSubImage3DImplementation)(level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); } #endif #ifndef MAGNUM_TARGET_GLES void AbstractTexture::DataHelper<1>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Math::Vector<1, GLint>& offset, const Math::Vector<1, GLint>& size) { - (texture.*Context::current().state().texture->invalidateSubImageImplementation)(level, {offset[0], 0, 0}, {size[0], 1, 1}); + (texture.*Context::current().state().texture.invalidateSubImageImplementation)(level, {offset[0], 0, 0}, {size[0], 1, 1}); } #endif void AbstractTexture::DataHelper<2>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Vector2i& offset, const Vector2i& size) { - (texture.*Context::current().state().texture->invalidateSubImageImplementation)(level, {offset, 0}, {size, 1}); + (texture.*Context::current().state().texture.invalidateSubImageImplementation)(level, {offset, 0}, {size, 1}); } void AbstractTexture::DataHelper<3>::invalidateSubImage(AbstractTexture& texture, const GLint level, const Vector3i& offset, const Vector3i& size) { - (texture.*Context::current().state().texture->invalidateSubImageImplementation)(level, offset, size); + (texture.*Context::current().state().texture.invalidateSubImageImplementation)(level, offset, size); } #ifndef MAGNUM_TARGET_GLES void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture& texture, const Array1D& wrapping) { - (texture.*Context::current().state().texture->parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); + (texture.*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); } #endif void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Array2D& wrapping) { - const Implementation::TextureState& state = *Context::current().state().texture; + const Implementation::TextureState& state = Context::current().state().texture; (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y())); @@ -2368,7 +2368,7 @@ void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Array3D& wrapping) { - const Implementation::TextureState& state = *Context::current().state().texture; + const Implementation::TextureState& state = Context::current().state().texture; (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_T, GLint(wrapping.y())); diff --git a/src/Magnum/GL/Buffer.cpp b/src/Magnum/GL/Buffer.cpp index 9c315940d..00f4d8449 100644 --- a/src/Magnum/GL/Buffer.cpp +++ b/src/Magnum/GL/Buffer.cpp @@ -49,7 +49,7 @@ Int Buffer::minMapAlignment() { if(!Context::current().isExtensionSupported()) return 1; - GLint& value = Context::current().state().buffer->minMapAlignment; + GLint& value = Context::current().state().buffer.minMapAlignment; if(value == 0) glGetIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &value); @@ -68,7 +68,7 @@ Int Buffer::maxAtomicCounterBindings() { #endif return 0; - GLint& value = Context::current().state().buffer->maxAtomicCounterBindings; + GLint& value = Context::current().state().buffer.maxAtomicCounterBindings; if(value == 0) glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &value); @@ -84,7 +84,7 @@ Int Buffer::maxShaderStorageBindings() { #endif return 0; - GLint& value = Context::current().state().buffer->maxShaderStorageBindings; + GLint& value = Context::current().state().buffer.maxShaderStorageBindings; if(value == 0) glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &value); @@ -99,7 +99,7 @@ Int Buffer::uniformOffsetAlignment() { return 1; #endif - GLint& value = Context::current().state().buffer->uniformOffsetAlignment; + GLint& value = Context::current().state().buffer.uniformOffsetAlignment; if(value == 0) glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &value); @@ -116,7 +116,7 @@ Int Buffer::shaderStorageOffsetAlignment() { #endif return 1; - GLint& value = Context::current().state().buffer->shaderStorageOffsetAlignment; + GLint& value = Context::current().state().buffer.shaderStorageOffsetAlignment; if(value == 0) glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &value); @@ -131,7 +131,7 @@ Int Buffer::maxUniformBindings() { return 0; #endif - GLint& value = Context::current().state().buffer->maxUniformBindings; + GLint& value = Context::current().state().buffer.maxUniformBindings; if(value == 0) glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &value); @@ -144,33 +144,33 @@ void Buffer::unbind(const Target target, const UnsignedInt index) { } void Buffer::unbind(const Target target, const UnsignedInt firstIndex, const std::size_t count) { - Context::current().state().buffer->bindBasesImplementation(target, firstIndex, {nullptr, count}); + Context::current().state().buffer.bindBasesImplementation(target, firstIndex, {nullptr, count}); } /** @todoc const std::initializer_list makes Doxygen grumpy */ void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list> buffers) { - Context::current().state().buffer->bindRangesImplementation(target, firstIndex, {buffers.begin(), buffers.size()}); + Context::current().state().buffer.bindRangesImplementation(target, firstIndex, {buffers.begin(), buffers.size()}); } /** @todoc const std::initializer_list makes Doxygen grumpy */ void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list buffers) { - Context::current().state().buffer->bindBasesImplementation(target, firstIndex, {buffers.begin(), buffers.size()}); + Context::current().state().buffer.bindBasesImplementation(target, firstIndex, {buffers.begin(), buffers.size()}); } void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) { - Context::current().state().buffer->copyImplementation(read, write, readOffset, writeOffset, size); + Context::current().state().buffer.copyImplementation(read, write, readOffset, writeOffset, size); } #endif Buffer::Buffer(const TargetHint targetHint): _flags{ObjectFlag::DeleteOnDestruction} { - Implementation::BufferState& state = *Context::current().state().buffer; + const Implementation::BufferState& state = Context::current().state().buffer; (this->*state.createImplementation)(); (this->*state.setTargetHintImplementation)(targetHint); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } Buffer::Buffer(GLuint id, TargetHint targetHint, ObjectFlags flags) noexcept: _id{id}, _flags{flags} { - (this->*Context::current().state().buffer->setTargetHintImplementation)(targetHint); + (this->*Context::current().state().buffer.setTargetHintImplementation)(targetHint); } void Buffer::createImplementationDefault() { @@ -188,7 +188,7 @@ Buffer::~Buffer() { /* Moved out or not deleting on destruction, nothing to do */ if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; - GLuint* bindings = Context::current().state().buffer->bindings; + GLuint* bindings = Context::current().state().buffer.bindings; /* Remove all current bindings from the state */ for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i) @@ -198,7 +198,7 @@ Buffer::~Buffer() { } Buffer& Buffer::setTargetHint(TargetHint hint) { - (this->*Context::current().state().buffer->setTargetHintImplementation)(hint); + (this->*Context::current().state().buffer.setTargetHintImplementation)(hint); return *this; } @@ -230,18 +230,18 @@ void Buffer::createIfNotAlready() { std::string Buffer::label() { createIfNotAlready(); #ifndef MAGNUM_TARGET_GLES2 - return Context::current().state().debug->getLabelImplementation(GL_BUFFER, _id); + return Context::current().state().debug.getLabelImplementation(GL_BUFFER, _id); #else - return Context::current().state().debug->getLabelImplementation(GL_BUFFER_KHR, _id); + return Context::current().state().debug.getLabelImplementation(GL_BUFFER_KHR, _id); #endif } Buffer& Buffer::setLabelInternal(const Containers::ArrayView label) { createIfNotAlready(); #ifndef MAGNUM_TARGET_GLES2 - Context::current().state().debug->labelImplementation(GL_BUFFER, _id, label); + Context::current().state().debug.labelImplementation(GL_BUFFER, _id, label); #else - Context::current().state().debug->labelImplementation(GL_BUFFER_KHR, _id, label); + Context::current().state().debug.labelImplementation(GL_BUFFER_KHR, _id, label); #endif return *this; } @@ -249,7 +249,7 @@ Buffer& Buffer::setLabelInternal(const Containers::ArrayView label) void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) { const GLuint id = buffer ? buffer->_id : 0; - GLuint& bound = Context::current().state().buffer->bindings[Implementation::BufferState::indexForTarget(target)]; + GLuint& bound = Context::current().state().buffer.bindings[Implementation::BufferState::indexForTarget(target)]; /* Already bound, nothing to do */ if(bound == id) return; @@ -261,7 +261,7 @@ void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) { } auto Buffer::bindSomewhereInternal(const TargetHint hint) -> TargetHint { - GLuint* bindings = Context::current().state().buffer->bindings; + GLuint* bindings = Context::current().state().buffer.bindings; GLuint& hintBinding = bindings[Implementation::BufferState::indexForTarget(hint)]; /* Shortcut - if already bound to hint, return */ @@ -279,11 +279,11 @@ auto Buffer::bindSomewhereInternal(const TargetHint hint) -> TargetHint { prevent accidental modification of that VAO. See Test::MeshGLTest::unbindVAOwhenSettingIndexBufferData() for details. */ if(hint == TargetHint::ElementArray) { - auto& currentVAO = Context::current().state().mesh->currentVAO; + auto& currentVAO = Context::current().state().mesh.currentVAO; /* It can be also State::DisengagedBinding, in which case we unbind as well to be sure */ if(currentVAO != 0) - Context::current().state().mesh->bindVAOImplementation(0); + Context::current().state().mesh.bindVAOImplementation(0); } /* Bind the buffer to hint target otherwise */ @@ -307,7 +307,7 @@ Buffer& Buffer::bind(const Target target, const UnsignedInt index) { #ifndef MAGNUM_TARGET_GLES Buffer& Buffer::setStorage(const Containers::ArrayView data, const StorageFlags flags) { - (this->*Context::current().state().buffer->storageImplementation)(data, flags); + (this->*Context::current().state().buffer.storageImplementation)(data, flags); return *this; } #endif @@ -318,7 +318,7 @@ Int Buffer::size() { * couldn't find any matching extension, though) */ GLint size; - (this->*Context::current().state().buffer->getParameterImplementation)(GL_BUFFER_SIZE, &size); + (this->*Context::current().state().buffer.getParameterImplementation)(GL_BUFFER_SIZE, &size); return size; } @@ -329,46 +329,46 @@ Containers::Array Buffer::data() { #endif Buffer& Buffer::setData(const Containers::ArrayView data, const BufferUsage usage) { - (this->*Context::current().state().buffer->dataImplementation)(data.size(), data, usage); + (this->*Context::current().state().buffer.dataImplementation)(data.size(), data, usage); return *this; } Buffer& Buffer::setSubData(const GLintptr offset, const Containers::ArrayView data) { - (this->*Context::current().state().buffer->subDataImplementation)(offset, data.size(), data); + (this->*Context::current().state().buffer.subDataImplementation)(offset, data.size(), data); return *this; } Buffer& Buffer::invalidateData() { - (this->*Context::current().state().buffer->invalidateImplementation)(); + (this->*Context::current().state().buffer.invalidateImplementation)(); return *this; } Buffer& Buffer::invalidateSubData(const GLintptr offset, const GLsizeiptr length) { - (this->*Context::current().state().buffer->invalidateSubImplementation)(offset, length); + (this->*Context::current().state().buffer.invalidateSubImplementation)(offset, length); return *this; } #ifndef MAGNUM_TARGET_WEBGL char* Buffer::map(const MapAccess access) { - return static_cast((this->*Context::current().state().buffer->mapImplementation)(access)); + return static_cast((this->*Context::current().state().buffer.mapImplementation)(access)); } Containers::ArrayView Buffer::map(const GLintptr offset, const GLsizeiptr length, const MapFlags flags) { - return {static_cast((this->*Context::current().state().buffer->mapRangeImplementation)(offset, length, flags)), std::size_t(length)}; + return {static_cast((this->*Context::current().state().buffer.mapRangeImplementation)(offset, length, flags)), std::size_t(length)}; } Buffer& Buffer::flushMappedRange(const GLintptr offset, const GLsizeiptr length) { - (this->*Context::current().state().buffer->flushMappedRangeImplementation)(offset, length); + (this->*Context::current().state().buffer.flushMappedRangeImplementation)(offset, length); return *this; } -bool Buffer::unmap() { return (this->*Context::current().state().buffer->unmapImplementation)(); } +bool Buffer::unmap() { return (this->*Context::current().state().buffer.unmapImplementation)(); } #endif #ifndef MAGNUM_TARGET_GLES Containers::Array Buffer::subData(const GLintptr offset, const GLsizeiptr size) { Containers::Array data(size); - if(size) (this->*Context::current().state().buffer->getSubDataImplementation)(offset, size, data); + if(size) (this->*Context::current().state().buffer.getSubDataImplementation)(offset, size, data); return data; } #endif @@ -573,7 +573,7 @@ void Buffer::textureWorkaroundAppleBefore() { /* My Mac Mini reports 80 texture units, which means this thing can have a pretty significant overhead. Skipping the whole thing if no buffer texture is known to be bound. */ - Implementation::TextureState& textureState = *Context::current().state().texture; + Implementation::TextureState& textureState = Context::current().state().texture; if(textureState.bufferTextureBound.none()) return; for(GLint textureUnit = 0; textureUnit != GLint(textureState.bindings.size()); ++textureUnit) { /* Checking just diff --git a/src/Magnum/GL/BufferTexture.cpp b/src/Magnum/GL/BufferTexture.cpp index 014856f4c..39f36cf1e 100644 --- a/src/Magnum/GL/BufferTexture.cpp +++ b/src/Magnum/GL/BufferTexture.cpp @@ -44,7 +44,7 @@ Int BufferTexture::maxSize() { return 0; #endif - GLint& value = Context::current().state().texture->maxBufferSize; + GLint& value = Context::current().state().texture.maxBufferSize; /* Get the value, if not already cached */ if(value == 0) @@ -62,7 +62,7 @@ Int BufferTexture::offsetAlignment() { return 0; #endif - GLint& value = Context::current().state().texture->bufferOffsetAlignment; + GLint& value = Context::current().state().texture.bufferOffsetAlignment; /* Get the value, if not already cached */ if(value == 0) @@ -75,19 +75,19 @@ Int BufferTexture::size() { /* Can't use DataHelper<1>::imageSize(*this, 0)[0] because for 1D textures it's not defined on ES */ Int size; - (this->*Context::current().state().texture->getLevelParameterivImplementation)(0, GL_TEXTURE_WIDTH, &size); + (this->*Context::current().state().texture.getLevelParameterivImplementation)(0, GL_TEXTURE_WIDTH, &size); return size; } BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer) { buffer.createIfNotAlready(); - (this->*Context::current().state().texture->setBufferImplementation)(internalFormat, &buffer); + (this->*Context::current().state().texture.setBufferImplementation)(internalFormat, &buffer); return *this; } BufferTexture& BufferTexture::setBuffer(const BufferTextureFormat internalFormat, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) { buffer.createIfNotAlready(); - (this->*Context::current().state().texture->setBufferRangeImplementation)(internalFormat, buffer, offset, size); + (this->*Context::current().state().texture.setBufferRangeImplementation)(internalFormat, buffer, offset, size); return *this; } @@ -130,7 +130,7 @@ void BufferTexture::setBufferRangeImplementationDSA(const BufferTextureFormat in BufferTexture& BufferTexture::resetBuffer() { /* R8 is the default state according to ARB_texture_buffer_object, so use that */ - (this->*Context::current().state().texture->setBufferImplementation)(BufferTextureFormat::R8, nullptr); + (this->*Context::current().state().texture.setBufferImplementation)(BufferTextureFormat::R8, nullptr); return *this; } diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index e1b2cb0ca..288a837b9 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -963,7 +963,9 @@ bool Context::tryCreate(const Configuration& configuration) { } } - _state.emplace(*this, output); + std::pair state = Implementation::State::allocate(*this, output); + _stateData = std::move(state.first); + _state = &state.second; /* Print a list of used workarounds */ if(!_driverWorkarounds.empty()) { @@ -1066,7 +1068,7 @@ Containers::Array Context::extensionStrings() const { #ifndef MAGNUM_TARGET_GLES bool Context::isCoreProfile() { - return isCoreProfileInternal(*_state->context); + return isCoreProfileInternal(_state->context); } bool Context::isCoreProfileInternal(Implementation::ContextState& state) { @@ -1137,45 +1139,45 @@ void Context::resetState(const States states) { #endif if(states & State::Buffers) - _state->buffer->reset(); + _state->buffer.reset(); if(states & State::Framebuffers) - _state->framebuffer->reset(); + _state->framebuffer.reset(); if(states & State::Meshes) - _state->mesh->reset(); + _state->mesh.reset(); #ifndef MAGNUM_TARGET_GLES /* Bind a scratch VAO for external GL code that is not VAO-aware and just enables vertex attributes on the default VAO. Generate it on-demand as we don't expect this case to be used very often. */ if(states & State::BindScratchVao) { - if(!_state->mesh->scratchVAO) - glGenVertexArrays(1, &_state->mesh->scratchVAO); + if(!_state->mesh.scratchVAO) + glGenVertexArrays(1, &_state->mesh.scratchVAO); - _state->mesh->bindVAOImplementation(_state->mesh->scratchVAO); + _state->mesh.bindVAOImplementation(_state->mesh.scratchVAO); /* Otherwise just unbind the current VAO and leave the the default */ } else #endif if(states & State::MeshVao) - _state->mesh->bindVAOImplementation(0); + _state->mesh.bindVAOImplementation(0); if(states & State::PixelStorage) { - _state->renderer->unpackPixelStorage.reset(); - _state->renderer->packPixelStorage.reset(); + _state->renderer.unpackPixelStorage.reset(); + _state->renderer.packPixelStorage.reset(); } /* Nothing to reset for renderer yet */ if(states & State::Shaders) { /* Nothing to reset for shaders */ - _state->shaderProgram->reset(); + _state->shaderProgram.reset(); } if(states & State::Textures) - _state->texture->reset(); + _state->texture.reset(); #ifndef MAGNUM_TARGET_GLES2 if(states & State::TransformFeedback) - _state->transformFeedback->reset(); + _state->transformFeedback.reset(); #endif } diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 3da9fcdf2..9d38e146a 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -31,9 +31,9 @@ #include #include +#include #include #include -#include #include #include "Magnum/Magnum.h" @@ -853,7 +853,8 @@ class MAGNUM_GL_EXPORT Context { Containers::Array _supportedExtensions; #endif - Containers::Pointer _state; + Containers::ArrayTuple _stateData; + Implementation::State* _state; Containers::Optional _detectedDrivers; diff --git a/src/Magnum/GL/CubeMapTexture.cpp b/src/Magnum/GL/CubeMapTexture.cpp index 7c27bd656..f92e634a5 100644 --- a/src/Magnum/GL/CubeMapTexture.cpp +++ b/src/Magnum/GL/CubeMapTexture.cpp @@ -53,7 +53,7 @@ Vector2i CubeMapTexture::maxSize() { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) Vector2i CubeMapTexture::imageSize(const Int level) { - const Implementation::TextureState& state = *Context::current().state().texture; + const Implementation::TextureState& state = Context::current().state().texture; Vector2i value; (this->*state.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_WIDTH, &value[0]); @@ -75,8 +75,8 @@ void CubeMapTexture::image(const Int level, Image3D& image) { data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getFullCubeImageImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data, image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getFullCubeImageImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data, image.storage()); image = Image3D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)}; } @@ -93,8 +93,8 @@ void CubeMapTexture::image(const Int level, const MutableImageView3D& image) { "GL::CubeMapTexture::image(): expected image view size" << size << "but got" << image.size(), ); Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getFullCubeImageImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data(), image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getFullCubeImageImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data(), image.storage()); } void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUsage usage) { @@ -110,8 +110,8 @@ void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUs image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getFullCubeImageImplementation)(level, size, image.format(), image.type(), dataSize, nullptr, image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getFullCubeImageImplementation)(level, size, image.format(), image.type(), dataSize, nullptr, image.storage()); } BufferImage3D CubeMapTexture::image(const Int level, BufferImage3D&& image, const BufferUsage usage) { @@ -133,12 +133,12 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image) nv-cubemap-broken-full-compressed-image-query workaround, where it needs to go slice-by-slice, advancing the offset each time */ dataOffsetSize.first = 0; - dataOffsetSize.second = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level)*6; + dataOffsetSize.second = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level)*6; } else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size); /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Reallocate only if needed */ Containers::Array data{image.release()}; @@ -146,8 +146,8 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image) data = Containers::Array{dataOffsetSize.first + dataOffsetSize.second}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, data); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, data); image = CompressedImage3D{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; } @@ -173,7 +173,7 @@ void CubeMapTexture::compressedImage(const Int level, const MutableCompressedIma nv-cubemap-broken-full-compressed-image-query workaround, where it needs to go slice-by-slice, advancing the offset each time */ dataOffsetSize.first = 0; - dataOffsetSize.second = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level)*6; + dataOffsetSize.second = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level)*6; } else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size); CORRADE_ASSERT(image.data().size() == dataOffsetSize.first + dataOffsetSize.second, @@ -182,15 +182,15 @@ void CubeMapTexture::compressedImage(const Int level, const MutableCompressedIma #ifndef CORRADE_NO_ASSERT /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), "GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); #endif Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, image.data()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, image.data()); } void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& image, const BufferUsage usage) { @@ -207,12 +207,12 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i nv-cubemap-broken-full-compressed-image-query workaround, where it needs to go slice-by-slice, advancing the offset each time */ dataOffsetSize.first = 0; - dataOffsetSize.second = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level)*6; + dataOffsetSize.second = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level)*6; } else dataOffsetSize = Magnum::Implementation::compressedImageDataOffsetSizeFor(image, size); /* Internal texture format */ GLint format; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Reallocate only if needed */ if(image.dataSize() < dataOffsetSize.first + dataOffsetSize.second) @@ -221,8 +221,8 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, nullptr); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, nullptr); } CompressedBufferImage3D CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D&& image, const BufferUsage usage) { @@ -240,8 +240,8 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data); image = Image2D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)}; } @@ -258,8 +258,8 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, "GL::CubeMapTexture::image(): expected image view size" << size << "but got" << image.size(), ); Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCubeImageImplementation)(coordinate, level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data()); } void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, BufferImage2D& image, const BufferUsage usage) { @@ -273,8 +273,8 @@ void CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, image.setData(image.storage(), image.format(), image.type(), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, nullptr); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCubeImageImplementation)(coordinate, level, size, image.format(), image.type(), dataSize, nullptr); } BufferImage2D CubeMapTexture::image(const CubeMapCoordinate coordinate, const Int level, BufferImage2D&& image, const BufferUsage usage) { @@ -289,7 +289,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I the compression, we need to ask GL for it */ std::size_t dataSize; if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) - dataSize = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level); + dataSize = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level); else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); @@ -297,7 +297,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I already wrapped in compressedPixelFormatWrap() later if the drivers are extra shitty (Intel Windows drivers, I'm talking about you). */ GLint format{}; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Reallocate only if needed */ Containers::Array data{image.release()}; @@ -305,8 +305,8 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, data.size(), data); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCompressedCubeImageImplementation)(coordinate, level, size, data.size(), data); image = CompressedImage2D{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; } @@ -328,7 +328,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I the compression, we need to ask GL for it */ std::size_t dataSize; if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) - dataSize = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level); + dataSize = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level); else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); @@ -339,15 +339,15 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I already wrapped in compressedPixelFormatWrap() later if the drivers are extra shitty (Intel Windows drivers, I'm talking about you). */ GLint format{}; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), "GL::CubeMapTexture::compressedImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); #endif Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, image.data().size(), image.data()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCompressedCubeImageImplementation)(coordinate, level, size, image.data().size(), image.data()); } void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, CompressedBufferImage2D& image, const BufferUsage usage) { @@ -357,7 +357,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I the compression, we need to ask GL for it */ std::size_t dataSize; if(!image.storage().compressedBlockSize().product() || !image.storage().compressedBlockDataSize()) - dataSize = (this->*Context::current().state().texture->getCubeLevelCompressedImageSizeImplementation)(level); + dataSize = (this->*Context::current().state().texture.getCubeLevelCompressedImageSizeImplementation)(level); else dataSize = Magnum::Implementation::compressedImageDataSizeFor(image, size); @@ -365,7 +365,7 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I already wrapped in compressedPixelFormatWrap() later if the drivers are extra shitty (Intel Windows drivers, I'm talking about you). */ GLint format{}; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Reallocate only if needed */ if(image.dataSize() < dataSize) @@ -374,8 +374,8 @@ void CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const I image.setData(image.storage(), CompressedPixelFormat(format), size, nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture->getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, nullptr); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); + (this->*Context::current().state().texture.getCompressedCubeImageImplementation)(coordinate, level, size, dataSize, nullptr); } CompressedBufferImage2D CubeMapTexture::compressedImage(const CubeMapCoordinate coordinate, const Int level, CompressedBufferImage2D&& image, const BufferUsage usage) { @@ -400,7 +400,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, already wrapped in compressedPixelFormatWrap() later if the drivers are extra shitty (Intel Windows drivers, I'm talking about you). */ GLint format{}; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Calculate compressed subimage size. If the user-provided pixel storage doesn't tell us all properties about the compression, we need to ask GL @@ -416,7 +416,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, data = Containers::Array{dataSize}; Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), data.size(), data); image = CompressedImage3D{CompressedPixelFormat(format), range.size(), std::move(data)}; } @@ -439,7 +439,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, already wrapped in compressedPixelFormatWrap() later if the drivers are extra shitty (Intel Windows drivers, I'm talking about you). */ GLint format{}; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); CORRADE_ASSERT(compressedPixelFormat(image.format()) == CompressedPixelFormat(format), "GL::CubeMapTexture::compressedSubImage(): expected image view format" << CompressedPixelFormat(format) << "but got" << compressedPixelFormat(image.format()), ); @@ -457,7 +457,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, #endif Buffer::unbindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), image.data().size(), image.data()); } @@ -468,7 +468,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, already wrapped in compressedPixelFormatWrap() later if the drivers are extra shitty (Intel Windows drivers, I'm talking about you). */ GLint format{}; - (this->*Context::current().state().texture->getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); + (this->*Context::current().state().texture.getCubeLevelParameterivImplementation)(level, GL_TEXTURE_INTERNAL_FORMAT, &format); /* Calculate compressed subimage size. If the user-provided pixel storage doesn't tell us all properties about the compression, we need to ask GL @@ -485,7 +485,7 @@ void CubeMapTexture::compressedSubImage(const Int level, const Range3Di& range, image.setData(image.storage(), CompressedPixelFormat(format), range.size(), nullptr, usage); image.buffer().bindInternal(Buffer::TargetHint::PixelPack); - Context::current().state().renderer->applyPixelStoragePack(image.storage()); + Context::current().state().renderer.applyPixelStoragePack(image.storage()); glGetCompressedTextureSubImage(_id, level, range.min().x(), range.min().y(), range.min().z(), range.size().x(), range.size().y(), range.size().z(), dataSize, nullptr); } @@ -498,8 +498,8 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& off createIfNotAlready(); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data(), image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (this->*Context::current().state().texture.cubeSubImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data(), image.storage()); return *this; } @@ -507,8 +507,8 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& off createIfNotAlready(); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (this->*Context::current().state().texture->cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (this->*Context::current().state().texture.cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); return *this; } @@ -516,7 +516,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vec createIfNotAlready(); Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(compressedPixelFormat(image.format())), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size()), image.data()); return *this; } @@ -525,7 +525,7 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vec createIfNotAlready(); image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); glCompressedTextureSubImage3D(_id, level, offset.x(), offset.y(), offset.z(), image.size().x(), image.size().y(), image.size().z(), GLenum(image.format()), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize()), nullptr); return *this; } @@ -535,8 +535,8 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (this->*Context::current().state().texture.cubeSubImageImplementation)(coordinate, level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() #ifdef MAGNUM_TARGET_GLES2 + Magnum::Implementation::pixelStorageSkipOffset(image) #endif @@ -547,8 +547,8 @@ CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, #ifndef MAGNUM_TARGET_GLES2 CubeMapTexture& CubeMapTexture::setSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, BufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (this->*Context::current().state().texture->cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), nullptr); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (this->*Context::current().state().texture.cubeSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), image.type(), nullptr); return *this; } #endif @@ -557,16 +557,16 @@ CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate co #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); #endif - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (this->*Context::current().state().texture.cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), compressedPixelFormat(image.format()), image.data(), Magnum::Implementation::occupiedCompressedImageDataSize(image, image.data().size())); return *this; } #ifndef MAGNUM_TARGET_GLES2 CubeMapTexture& CubeMapTexture::setCompressedSubImage(const CubeMapCoordinate coordinate, const Int level, const Vector2i& offset, CompressedBufferImage2D& image) { image.buffer().bindInternal(Buffer::TargetHint::PixelUnpack); - Context::current().state().renderer->applyPixelStorageUnpack(image.storage()); - (this->*Context::current().state().texture->cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); + Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); + (this->*Context::current().state().texture.cubeCompressedSubImageImplementation)(coordinate, level, offset, image.size(), image.format(), nullptr, Magnum::Implementation::occupiedCompressedImageDataSize(image, image.dataSize())); return *this; } #endif diff --git a/src/Magnum/GL/DebugOutput.cpp b/src/Magnum/GL/DebugOutput.cpp index 992f4647f..e5a68e07e 100644 --- a/src/Magnum/GL/DebugOutput.cpp +++ b/src/Magnum/GL/DebugOutput.cpp @@ -114,7 +114,7 @@ Int DebugOutput::maxLoggedMessages() { if(!Context::current().isExtensionSupported()) return 0; - GLint& value = Context::current().state().debug->maxLoggedMessages; + GLint& value = Context::current().state().debug.maxLoggedMessages; if(value == 0) { #ifndef MAGNUM_TARGET_GLES2 @@ -131,7 +131,7 @@ Int DebugOutput::maxMessageLength() { if(!Context::current().isExtensionSupported()) return 0; - GLint& value = Context::current().state().debug->maxMessageLength; + GLint& value = Context::current().state().debug.maxMessageLength; if(value == 0) { #ifndef MAGNUM_TARGET_GLES2 @@ -145,7 +145,7 @@ Int DebugOutput::maxMessageLength() { } void DebugOutput::setCallback(const Callback callback, const void* userParam) { - Context::current().state().debug->callbackImplementation(callback, userParam); + Context::current().state().debug.callbackImplementation(callback, userParam); } void DebugOutput::setDefaultCallback() { @@ -155,7 +155,7 @@ void DebugOutput::setDefaultCallback() { } void DebugOutput::setEnabledInternal(const GLenum source, const GLenum type, const GLenum severity, const std::initializer_list ids, const bool enabled) { - Context::current().state().debug->controlImplementation(source, type, severity, ids, enabled); + Context::current().state().debug.controlImplementation(source, type, severity, ids, enabled); } void DebugOutput::controlImplementationNoOp(GLenum, GLenum, GLenum, std::initializer_list, bool) {} @@ -177,13 +177,13 @@ void DebugOutput::callbackImplementationNoOp(Callback, const void*) {} #ifndef MAGNUM_TARGET_GLES2 void DebugOutput::callbackImplementationKhrDesktopES32(const Callback callback, const void* userParam) { /* Replace the callback */ - const Callback original = Context::current().state().debug->messageCallback.callback; - Context::current().state().debug->messageCallback.callback = callback; - Context::current().state().debug->messageCallback.userParam = userParam; + const Callback original = Context::current().state().debug.messageCallback.callback; + Context::current().state().debug.messageCallback.callback = callback; + Context::current().state().debug.messageCallback.userParam = userParam; /* Adding callback */ if(!original && callback) - glDebugMessageCallback(callbackWrapper, &Context::current().state().debug->messageCallback); + glDebugMessageCallback(callbackWrapper, &Context::current().state().debug.messageCallback); /* Deleting callback */ else if(original && !callback) @@ -194,13 +194,13 @@ void DebugOutput::callbackImplementationKhrDesktopES32(const Callback callback, #ifdef MAGNUM_TARGET_GLES void DebugOutput::callbackImplementationKhrES(const Callback callback, const void* userParam) { /* Replace the callback */ - const Callback original = Context::current().state().debug->messageCallback.callback; - Context::current().state().debug->messageCallback.callback = callback; - Context::current().state().debug->messageCallback.userParam = userParam; + const Callback original = Context::current().state().debug.messageCallback.callback; + Context::current().state().debug.messageCallback.callback = callback; + Context::current().state().debug.messageCallback.userParam = userParam; /* Adding callback */ if(!original && callback) - glDebugMessageCallbackKHR(callbackWrapper, &Context::current().state().debug->messageCallback); + glDebugMessageCallbackKHR(callbackWrapper, &Context::current().state().debug.messageCallback); /* Deleting callback */ else if(original && !callback) @@ -267,7 +267,7 @@ Debug& operator<<(Debug& debug, const DebugOutput::Severity value) { #endif void DebugMessage::insertInternal(const Source source, const Type type, const UnsignedInt id, const DebugOutput::Severity severity, const Containers::ArrayView string) { - Context::current().state().debug->messageInsertImplementation(source, type, id, severity, string); + Context::current().state().debug.messageInsertImplementation(source, type, id, severity, string); } void DebugMessage::insertImplementationNoOp(Source, Type, UnsignedInt, DebugOutput::Severity, const Containers::ArrayView) {} @@ -333,7 +333,7 @@ Int DebugGroup::maxStackDepth() { if(!Context::current().isExtensionSupported()) return 0; - GLint& value = Context::current().state().debug->maxStackDepth; + GLint& value = Context::current().state().debug.maxStackDepth; if(value == 0) { #ifndef MAGNUM_TARGET_GLES2 @@ -348,13 +348,13 @@ Int DebugGroup::maxStackDepth() { void DebugGroup::pushInternal(const Source source, const UnsignedInt id, const Containers::ArrayView message) { CORRADE_ASSERT(!_active, "GL::DebugGroup::push(): group is already active", ); - Context::current().state().debug->pushGroupImplementation(source, id, message); + Context::current().state().debug.pushGroupImplementation(source, id, message); _active = true; } void DebugGroup::pop() { CORRADE_ASSERT(_active, "GL::DebugGroup::pop(): group is not active", ); - Context::current().state().debug->popGroupImplementation(); + Context::current().state().debug.popGroupImplementation(); _active = false; } diff --git a/src/Magnum/GL/DefaultFramebuffer.cpp b/src/Magnum/GL/DefaultFramebuffer.cpp index e5de6500f..b86c3b852 100644 --- a/src/Magnum/GL/DefaultFramebuffer.cpp +++ b/src/Magnum/GL/DefaultFramebuffer.cpp @@ -40,22 +40,22 @@ namespace Magnum { namespace GL { DefaultFramebuffer defaultFramebuffer; DefaultFramebuffer::Status DefaultFramebuffer::checkStatus(const FramebufferTarget target) { - return Status((this->*Context::current().state().framebuffer->checkStatusImplementation)(target)); + return Status((this->*Context::current().state().framebuffer.checkStatusImplementation)(target)); } #ifndef MAGNUM_TARGET_GLES2 DefaultFramebuffer& DefaultFramebuffer::clearColor(const Color4& color) { - (this->*Context::current().state().framebuffer->clearFImplementation)(GL_COLOR, 0, color.data()); + (this->*Context::current().state().framebuffer.clearFImplementation)(GL_COLOR, 0, color.data()); return *this; } DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4i& color) { - (this->*Context::current().state().framebuffer->clearIImplementation)(GL_COLOR, 0, color.data()); + (this->*Context::current().state().framebuffer.clearIImplementation)(GL_COLOR, 0, color.data()); return *this; } DefaultFramebuffer& DefaultFramebuffer::clearColor(const Vector4ui& color) { - (this->*Context::current().state().framebuffer->clearUIImplementation)(GL_COLOR, 0, color.data()); + (this->*Context::current().state().framebuffer.clearUIImplementation)(GL_COLOR, 0, color.data()); return *this; } #endif @@ -73,22 +73,22 @@ DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list*Context::current().state().framebuffer->drawBuffersImplementation)(max+1, _attachments); + (this->*Context::current().state().framebuffer.drawBuffersImplementation)(max+1, _attachments); return *this; } DefaultFramebuffer& DefaultFramebuffer::mapForDraw(const DrawAttachment attachment) { #ifndef MAGNUM_TARGET_GLES - (this->*Context::current().state().framebuffer->drawBufferImplementation)(GLenum(attachment)); + (this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment)); #else - (this->*Context::current().state().framebuffer->drawBuffersImplementation)(1, reinterpret_cast(&attachment)); + (this->*Context::current().state().framebuffer.drawBuffersImplementation)(1, reinterpret_cast(&attachment)); #endif return *this; } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) DefaultFramebuffer& DefaultFramebuffer::mapForRead(const ReadAttachment attachment) { - (this->*Context::current().state().framebuffer->readBufferImplementation)(GLenum(attachment)); + (this->*Context::current().state().framebuffer.readBufferImplementation)(GLenum(attachment)); return *this; } @@ -98,7 +98,7 @@ void DefaultFramebuffer::invalidate(std::initializer_list*Context::current().state().framebuffer->invalidateImplementation)(attachments.size(), _attachments); + (this->*Context::current().state().framebuffer.invalidateImplementation)(attachments.size(), _attachments); } #endif @@ -109,12 +109,12 @@ void DefaultFramebuffer::invalidate(std::initializer_list*Context::current().state().framebuffer->invalidateSubImplementation)(attachments.size(), _attachments, rectangle); + (this->*Context::current().state().framebuffer.invalidateSubImplementation)(attachments.size(), _attachments, rectangle); } #endif void DefaultFramebuffer::initializeContextBasedFunctionality(Context& context) { - Implementation::FramebufferState& state = *context.state().framebuffer; + Implementation::FramebufferState& state = context.state().framebuffer; /* Initial framebuffer size */ GLint viewport[4]; diff --git a/src/Magnum/GL/Framebuffer.cpp b/src/Magnum/GL/Framebuffer.cpp index 1125eaaa4..135534bdf 100644 --- a/src/Magnum/GL/Framebuffer.cpp +++ b/src/Magnum/GL/Framebuffer.cpp @@ -84,7 +84,7 @@ Int Framebuffer::maxColorAttachments() { #endif #endif - GLint& value = Context::current().state().framebuffer->maxColorAttachments; + GLint& value = Context::current().state().framebuffer.maxColorAttachments; if(value == 0) { #ifndef MAGNUM_TARGET_GLES2 @@ -100,7 +100,7 @@ Int Framebuffer::maxColorAttachments() { Framebuffer::Framebuffer(const Range2Di& viewport): AbstractFramebuffer{0, viewport, ObjectFlag::DeleteOnDestruction} { CORRADE_INTERNAL_ASSERT(viewport != Implementation::FramebufferState::DisengagedViewport); _viewport = viewport; - (this->*Context::current().state().framebuffer->createImplementation)(); + (this->*Context::current().state().framebuffer.createImplementation)(); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } @@ -120,7 +120,7 @@ Framebuffer::~Framebuffer() { if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; /* If bound, remove itself from state */ - Implementation::FramebufferState& state = *Context::current().state().framebuffer; + Implementation::FramebufferState& state = Context::current().state().framebuffer; if(state.readBinding == _id) state.readBinding = 0; /* For draw binding reset also viewport */ @@ -140,33 +140,33 @@ Framebuffer::~Framebuffer() { #ifndef MAGNUM_TARGET_WEBGL std::string Framebuffer::label() { createIfNotAlready(); - return Context::current().state().debug->getLabelImplementation(GL_FRAMEBUFFER, _id); + return Context::current().state().debug.getLabelImplementation(GL_FRAMEBUFFER, _id); } Framebuffer& Framebuffer::setLabelInternal(const Containers::ArrayView label) { createIfNotAlready(); - Context::current().state().debug->labelImplementation(GL_FRAMEBUFFER, _id, label); + Context::current().state().debug.labelImplementation(GL_FRAMEBUFFER, _id, label); return *this; } #endif Framebuffer::Status Framebuffer::checkStatus(const FramebufferTarget target) { - return Status((this->*Context::current().state().framebuffer->checkStatusImplementation)(target)); + return Status((this->*Context::current().state().framebuffer.checkStatusImplementation)(target)); } #ifndef MAGNUM_TARGET_GLES2 Framebuffer& Framebuffer::clearColor(const Int attachment, const Color4& color) { - (this->*Context::current().state().framebuffer->clearFImplementation)(GL_COLOR, attachment, color.data()); + (this->*Context::current().state().framebuffer.clearFImplementation)(GL_COLOR, attachment, color.data()); return *this; } Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4i& color) { - (this->*Context::current().state().framebuffer->clearIImplementation)(GL_COLOR, attachment, color.data()); + (this->*Context::current().state().framebuffer.clearIImplementation)(GL_COLOR, attachment, color.data()); return *this; } Framebuffer& Framebuffer::clearColor(const Int attachment, const Vector4ui& color) { - (this->*Context::current().state().framebuffer->clearUIImplementation)(GL_COLOR, attachment, color.data()); + (this->*Context::current().state().framebuffer.clearUIImplementation)(GL_COLOR, attachment, color.data()); return *this; } #endif @@ -184,22 +184,22 @@ Framebuffer& Framebuffer::mapForDraw(std::initializer_list*Context::current().state().framebuffer->drawBuffersImplementation)(max+1, _attachments); + (this->*Context::current().state().framebuffer.drawBuffersImplementation)(max+1, _attachments); return *this; } Framebuffer& Framebuffer::mapForDraw(const DrawAttachment attachment) { #ifndef MAGNUM_TARGET_GLES - (this->*Context::current().state().framebuffer->drawBufferImplementation)(GLenum(attachment)); + (this->*Context::current().state().framebuffer.drawBufferImplementation)(GLenum(attachment)); #else - (this->*Context::current().state().framebuffer->drawBuffersImplementation)(1, reinterpret_cast(&attachment)); + (this->*Context::current().state().framebuffer.drawBuffersImplementation)(1, reinterpret_cast(&attachment)); #endif return *this; } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) Framebuffer& Framebuffer::mapForRead(const ColorAttachment attachment) { - (this->*Context::current().state().framebuffer->readBufferImplementation)(GLenum(attachment)); + (this->*Context::current().state().framebuffer.readBufferImplementation)(GLenum(attachment)); return *this; } @@ -209,7 +209,7 @@ void Framebuffer::invalidate(std::initializer_list attac for(std::size_t i = 0; i != attachments.size(); ++i) _attachments[i] = GLenum(*(attachments.begin()+i)); - (this->*Context::current().state().framebuffer->invalidateImplementation)(attachments.size(), _attachments); + (this->*Context::current().state().framebuffer.invalidateImplementation)(attachments.size(), _attachments); } #ifndef MAGNUM_TARGET_GLES2 @@ -219,116 +219,116 @@ void Framebuffer::invalidate(std::initializer_list attac for(std::size_t i = 0; i != attachments.size(); ++i) _attachments[i] = GLenum(*(attachments.begin()+i)); - (this->*Context::current().state().framebuffer->invalidateSubImplementation)(attachments.size(), _attachments, rectangle); + (this->*Context::current().state().framebuffer.invalidateSubImplementation)(attachments.size(), _attachments, rectangle); } #endif #endif Framebuffer& Framebuffer::attachRenderbuffer(const BufferAttachment attachment, Renderbuffer& renderbuffer) { - (this->*Context::current().state().framebuffer->renderbufferImplementation)(attachment, renderbuffer.id()); + (this->*Context::current().state().framebuffer.renderbufferImplementation)(attachment, renderbuffer.id()); return *this; } #ifndef MAGNUM_TARGET_GLES Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Texture1D& texture, const Int level) { - (this->*Context::current().state().framebuffer->texture1DImplementation)(attachment, texture.id(), level); + (this->*Context::current().state().framebuffer.texture1DImplementation)(attachment, texture.id(), level); return *this; } #endif Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, Texture2D& texture, const Int level) { - (this->*Context::current().state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D, texture.id(), level); + (this->*Context::current().state().framebuffer.texture2DImplementation)(attachment, GL_TEXTURE_2D, texture.id(), level); return *this; } #ifndef MAGNUM_TARGET_GLES Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, RectangleTexture& texture) { - (this->*Context::current().state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_RECTANGLE, texture.id(), 0); + (this->*Context::current().state().framebuffer.texture2DImplementation)(attachment, GL_TEXTURE_RECTANGLE, texture.id(), 0); return *this; } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) Framebuffer& Framebuffer::attachTexture(const BufferAttachment attachment, MultisampleTexture2D& texture) { - (this->*Context::current().state().framebuffer->texture2DImplementation)(attachment, GL_TEXTURE_2D_MULTISAMPLE, texture.id(), 0); + (this->*Context::current().state().framebuffer.texture2DImplementation)(attachment, GL_TEXTURE_2D_MULTISAMPLE, texture.id(), 0); return *this; } #endif Framebuffer& Framebuffer::attachCubeMapTexture(const BufferAttachment attachment, CubeMapTexture& texture, CubeMapCoordinate coordinate, const Int level) { - (this->*Context::current().state().framebuffer->textureCubeMapImplementation)(attachment, GLenum(coordinate), texture.id(), level); + (this->*Context::current().state().framebuffer.textureCubeMapImplementation)(attachment, GLenum(coordinate), texture.id(), level); return *this; } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture3D& texture, Int level, Int layer) { - (this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); + (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), level, layer); return *this; } #endif #ifndef MAGNUM_TARGET_GLES Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture1DArray& texture, Int level, Int layer) { - (this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); + (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), level, layer); return *this; } #endif #ifndef MAGNUM_TARGET_GLES2 Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, Texture2DArray& texture, Int level, Int layer) { - (this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); + (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), level, layer); return *this; } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, CubeMapTextureArray& texture, Int level, Int layer) { - (this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), level, layer); + (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), level, layer); return *this; } Framebuffer& Framebuffer::attachTextureLayer(const BufferAttachment attachment, MultisampleTexture2DArray& texture, Int layer) { - (this->*Context::current().state().framebuffer->textureLayerImplementation)(attachment, texture.id(), 0, layer); + (this->*Context::current().state().framebuffer.textureLayerImplementation)(attachment, texture.id(), 0, layer); return *this; } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture3D& texture, const Int level) { - (this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), level); + (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), level); return *this; } #ifndef MAGNUM_TARGET_GLES Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture1DArray& texture, const Int level) { - (this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), level); + (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), level); return *this; } #endif Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, Texture2DArray& texture, const Int level) { - (this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), level); + (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), level); return *this; } Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, CubeMapTexture& texture, const Int level) { - (this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), level); + (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), level); return *this; } Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, CubeMapTextureArray& texture, const Int level) { - (this->*Context::current().state().framebuffer->layeredTextureCubeMapArrayImplementation)(attachment, texture.id(), level); + (this->*Context::current().state().framebuffer.layeredTextureCubeMapArrayImplementation)(attachment, texture.id(), level); return *this; } Framebuffer& Framebuffer::attachLayeredTexture(const BufferAttachment attachment, MultisampleTexture2DArray& texture) { - (this->*Context::current().state().framebuffer->textureImplementation)(attachment, texture.id(), 0); + (this->*Context::current().state().framebuffer.textureImplementation)(attachment, texture.id(), 0); return *this; } #endif Framebuffer& Framebuffer::detach(const BufferAttachment attachment) { - (this->*Context::current().state().framebuffer->renderbufferImplementation)(attachment, 0); + (this->*Context::current().state().framebuffer.renderbufferImplementation)(attachment, 0); return *this; } diff --git a/src/Magnum/GL/Implementation/State.cpp b/src/Magnum/GL/Implementation/State.cpp index 558f87776..27d21cc55 100644 --- a/src/Magnum/GL/Implementation/State.cpp +++ b/src/Magnum/GL/Implementation/State.cpp @@ -25,6 +25,8 @@ #include "State.h" +#include + #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" #include "Magnum/GL/Implementation/BufferState.h" @@ -45,7 +47,43 @@ namespace Magnum { namespace GL { namespace Implementation { -State::State(Context& context, std::ostream* const out) { +std::pair State::allocate(Context& context, std::ostream* const out) { + /* I have to say, the ArrayTuple is quite a crazy thing */ + Containers::ArrayView stateView; + Containers::ArrayView bufferStateView; + Containers::ArrayView contextStateView; + #ifndef MAGNUM_TARGET_WEBGL + Containers::ArrayView debugStateView; + #endif + Containers::ArrayView framebufferStateView; + Containers::ArrayView meshStateView; + Containers::ArrayView queryStateView; + Containers::ArrayView rendererStateView; + Containers::ArrayView shaderStateView; + Containers::ArrayView shaderProgramStateView; + Containers::ArrayView textureStateView; + #ifndef MAGNUM_TARGET_GLES2 + Containers::ArrayView transformFeedbackStateView; + #endif + Containers::ArrayTuple data{ + {Containers::NoInit, 1, stateView}, + {Containers::NoInit, 1, bufferStateView}, + {Containers::NoInit, 1, contextStateView}, + #ifndef MAGNUM_TARGET_WEBGL + {Containers::NoInit, 1, debugStateView}, + #endif + {Containers::NoInit, 1, framebufferStateView}, + {Containers::NoInit, 1, meshStateView}, + {Containers::NoInit, 1, queryStateView}, + {Containers::NoInit, 1, rendererStateView}, + {Containers::NoInit, 1, shaderStateView}, + {Containers::NoInit, 1, shaderProgramStateView}, + {Containers::NoInit, 1, textureStateView}, + #ifndef MAGNUM_TARGET_GLES2 + {Containers::NoInit, 1, transformFeedbackStateView} + #endif + }; + /* Extensions that might get used by current context. The State classes will set strings based on Extension::index() and then we'll go through the list and print ones that aren't null. It's 1.5 kB of temporary data @@ -53,27 +91,45 @@ State::State(Context& context, std::ostream* const out) { populating a heap array and then std::sort() it to remove duplicates. */ const char* extensions[Implementation::ExtensionCount]{}; - buffer.reset(new BufferState{context, extensions}); - this->context.reset(new ContextState{context, extensions}); + State& state = *(new(&stateView.front()) State{ + bufferStateView.front(), + contextStateView.front(), + #ifndef MAGNUM_TARGET_WEBGL + debugStateView.front(), + #endif + framebufferStateView.front(), + meshStateView.front(), + queryStateView.front(), + rendererStateView.front(), + shaderStateView.front(), + shaderProgramStateView.front(), + textureStateView.front(), + #ifndef MAGNUM_TARGET_GLES2 + transformFeedbackStateView.front() + #endif + }); + + new(&state.buffer) BufferState{context, extensions}; + new(&state.context) ContextState{context, extensions}; #ifndef MAGNUM_TARGET_WEBGL - debug.reset(new DebugState{context, extensions}); + new(&state.debug) DebugState{context, extensions}; #endif - framebuffer.reset(new FramebufferState{context, extensions}); - mesh.reset(new MeshState{context, *this->context, extensions}); - query.reset(new QueryState{context, extensions}); - renderer.reset(new RendererState{context, *this->context, extensions}); - shader.reset(new ShaderState(context, extensions)); - shaderProgram.reset(new ShaderProgramState{context, extensions}); - texture.reset(new TextureState{context, extensions}); + new(&state.framebuffer) FramebufferState{context, extensions}; + new(&state.mesh) MeshState{context, stateView.front().context, extensions}; + new(&state.query) QueryState{context, extensions}; + new(&state.renderer) RendererState{context, stateView.front().context, extensions}; + new(&state.shader) ShaderState(context, extensions); + new(&state.shaderProgram) ShaderProgramState{context, extensions}; + new(&state.texture) TextureState{context, extensions}; #ifndef MAGNUM_TARGET_GLES2 - transformFeedback.reset(new TransformFeedbackState{context, extensions}); + new(&state.transformFeedback) TransformFeedbackState{context, extensions}; #endif Debug{out} << "Using optional features:"; for(const char* extension: extensions) if(extension) Debug(out) << " " << extension; -} -State::~State() = default; + return {std::move(data), state}; +} }}} diff --git a/src/Magnum/GL/Implementation/State.h b/src/Magnum/GL/Implementation/State.h index 6f1884ce0..f3bf2884f 100644 --- a/src/Magnum/GL/Implementation/State.h +++ b/src/Magnum/GL/Implementation/State.h @@ -25,7 +25,9 @@ DEALINGS IN THE SOFTWARE. */ -#include +#include +#include +#include #include "Magnum/Magnum.h" #include "Magnum/GL/GL.h" @@ -49,27 +51,26 @@ struct TransformFeedbackState; #endif struct State { - /* Initializes context-based functionality */ - explicit State(Context& context, std::ostream* out); - - ~State(); + /* Initializes context-based functionality together with all nested classes + in a single allocation */ + static std::pair allocate(Context& context, std::ostream* out); enum: GLuint { DisengagedBinding = ~0u }; - Containers::Pointer buffer; - Containers::Pointer context; + BufferState& buffer; + ContextState& context; #ifndef MAGNUM_TARGET_WEBGL - Containers::Pointer debug; + DebugState& debug; #endif - Containers::Pointer framebuffer; - Containers::Pointer mesh; - Containers::Pointer query; - Containers::Pointer renderer; - Containers::Pointer shader; - Containers::Pointer shaderProgram; - Containers::Pointer texture; + FramebufferState& framebuffer; + MeshState& mesh; + QueryState& query; + RendererState& renderer; + ShaderState& shader; + ShaderProgramState& shaderProgram; + TextureState& texture; #ifndef MAGNUM_TARGET_GLES2 - Containers::Pointer transformFeedback; + TransformFeedbackState& transformFeedback; #endif }; diff --git a/src/Magnum/GL/Implementation/maxTextureSize.cpp b/src/Magnum/GL/Implementation/maxTextureSize.cpp index 458a23559..c268dca39 100644 --- a/src/Magnum/GL/Implementation/maxTextureSize.cpp +++ b/src/Magnum/GL/Implementation/maxTextureSize.cpp @@ -32,7 +32,7 @@ namespace Magnum { namespace GL { namespace Implementation { GLint maxTextureSideSize() { - GLint& value = Context::current().state().texture->maxSize; + GLint& value = Context::current().state().texture.maxSize; if(value == 0) glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); @@ -42,7 +42,7 @@ GLint maxTextureSideSize() { #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) GLint max3DTextureDepth() { - GLint& value = Context::current().state().texture->max3DSize; + GLint& value = Context::current().state().texture.max3DSize; if(value == 0) #ifndef MAGNUM_TARGET_GLES2 @@ -57,7 +57,7 @@ GLint max3DTextureDepth() { #ifndef MAGNUM_TARGET_GLES2 GLint maxTextureArrayLayers() { - GLint& value = Context::current().state().texture->maxArrayLayers; + GLint& value = Context::current().state().texture.maxArrayLayers; if(value == 0) glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &value); @@ -67,7 +67,7 @@ GLint maxTextureArrayLayers() { #endif GLint maxCubeMapTextureSideSize() { - GLint& value = Context::current().state().texture->maxCubeMapSize; + GLint& value = Context::current().state().texture.maxCubeMapSize; if(value == 0) glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &value); diff --git a/src/Magnum/GL/Mesh.cpp b/src/Magnum/GL/Mesh.cpp index 3fa160a1f..c236f51eb 100644 --- a/src/Magnum/GL/Mesh.cpp +++ b/src/Magnum/GL/Mesh.cpp @@ -181,7 +181,7 @@ UnsignedInt Mesh::maxVertexAttributeStride() { } #ifndef MAGNUM_TARGET_GLES2 - GLint& value = Context::current().state().mesh->maxVertexAttributeStride; + GLint& value = Context::current().state().mesh.maxVertexAttributeStride; /* Get the value, if not already cached */ if(value == 0) @@ -209,7 +209,7 @@ Int Mesh::maxElementIndex() #else GLint& value = #endif - Context::current().state().mesh->maxElementIndex; + Context::current().state().mesh.maxElementIndex; /* Get the value, if not already cached */ if(value == 0) { @@ -224,7 +224,7 @@ Int Mesh::maxElementIndex() } Int Mesh::maxElementsIndices() { - GLint& value = Context::current().state().mesh->maxElementsIndices; + GLint& value = Context::current().state().mesh.maxElementsIndices; /* Get the value, if not already cached */ if(value == 0) @@ -234,7 +234,7 @@ Int Mesh::maxElementsIndices() { } Int Mesh::maxElementsVertices() { - GLint& value = Context::current().state().mesh->maxElementsVertices; + GLint& value = Context::current().state().mesh.maxElementsVertices; /* Get the value, if not already cached */ if(value == 0) @@ -245,7 +245,7 @@ Int Mesh::maxElementsVertices() { #endif Mesh::Mesh(const MeshPrimitive primitive): _primitive{primitive}, _flags{ObjectFlag::DeleteOnDestruction} { - (this->*Context::current().state().mesh->createImplementation)(true); + (this->*Context::current().state().mesh.createImplementation)(true); } Mesh::Mesh(NoCreateT) noexcept: _id{0}, _primitive{MeshPrimitive::Triangles}, _flags{ObjectFlag::DeleteOnDestruction} {} @@ -256,11 +256,11 @@ Mesh::~Mesh() { /* Moved out or not deleting on destruction, nothing to do */ if(deleteObject) { /* Remove current vao from the state */ - GLuint& current = Context::current().state().mesh->currentVAO; + GLuint& current = Context::current().state().mesh.currentVAO; if(current == _id) current = 0; } - if(_constructed) (this->*Context::current().state().mesh->destroyImplementation)(deleteObject); + if(_constructed) (this->*Context::current().state().mesh.destroyImplementation)(deleteObject); } Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _flags{other._flags}, _countSet{other._countSet}, _count(other._count), _baseVertex{other._baseVertex}, _instanceCount{other._instanceCount}, @@ -273,7 +273,7 @@ Mesh::Mesh(Mesh&& other) noexcept: _id(other._id), _primitive(other._primitive), _indexOffset(other._indexOffset), _indexType(other._indexType), _indexBuffer{std::move(other._indexBuffer)} { if(_constructed || other._constructed) - (this->*Context::current().state().mesh->moveConstructImplementation)(std::move(other)); + (this->*Context::current().state().mesh.moveConstructImplementation)(std::move(other)); other._id = 0; } @@ -298,13 +298,13 @@ Mesh& Mesh::operator=(Mesh&& other) noexcept { swap(_indexBuffer, other._indexBuffer); if(_constructed || other._constructed) - (this->*Context::current().state().mesh->moveAssignImplementation)(std::move(other)); + (this->*Context::current().state().mesh.moveAssignImplementation)(std::move(other)); return *this; } Mesh::Mesh(const GLuint id, const MeshPrimitive primitive, const ObjectFlags flags): _id{id}, _primitive{primitive}, _flags{flags} { - (this->*Context::current().state().mesh->createImplementation)(false); + (this->*Context::current().state().mesh.createImplementation)(false); } inline void Mesh::createIfNotAlready() { @@ -323,18 +323,18 @@ inline void Mesh::createIfNotAlready() { std::string Mesh::label() { createIfNotAlready(); #ifndef MAGNUM_TARGET_GLES2 - return Context::current().state().debug->getLabelImplementation(GL_VERTEX_ARRAY, _id); + return Context::current().state().debug.getLabelImplementation(GL_VERTEX_ARRAY, _id); #else - return Context::current().state().debug->getLabelImplementation(GL_VERTEX_ARRAY_KHR, _id); + return Context::current().state().debug.getLabelImplementation(GL_VERTEX_ARRAY_KHR, _id); #endif } Mesh& Mesh::setLabelInternal(const Containers::ArrayView label) { createIfNotAlready(); #ifndef MAGNUM_TARGET_GLES2 - Context::current().state().debug->labelImplementation(GL_VERTEX_ARRAY, _id, label); + Context::current().state().debug.labelImplementation(GL_VERTEX_ARRAY, _id, label); #else - Context::current().state().debug->labelImplementation(GL_VERTEX_ARRAY_KHR, _id, label); + Context::current().state().debug.labelImplementation(GL_VERTEX_ARRAY_KHR, _id, label); #endif return *this; } @@ -381,7 +381,7 @@ Mesh& Mesh::setIndexBuffer(Buffer&& buffer, GLintptr offset, MeshIndexType type, /* It's IMPORTANT to do this *before* the _indexBuffer is set, since the bindVAO() function called from here is resetting element buffer state tracker to _indexBuffer.id(). */ - (this->*Context::current().state().mesh->bindIndexBufferImplementation)(buffer); + (this->*Context::current().state().mesh.bindIndexBufferImplementation)(buffer); _indexBuffer = std::move(buffer); _indexOffset = offset; @@ -407,7 +407,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedIn void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset) #endif { - const Implementation::MeshState& state = *Context::current().state().mesh; + const Implementation::MeshState& state = Context::current().state().mesh; (this->*state.bindImplementation)(); @@ -548,7 +548,7 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i #ifndef MAGNUM_TARGET_GLES void Mesh::drawInternal(TransformFeedback& xfb, const UnsignedInt stream, const Int instanceCount) { - const Implementation::MeshState& state = *Context::current().state().mesh; + const Implementation::MeshState& state = Context::current().state().mesh; (this->*state.bindImplementation)(); @@ -605,11 +605,11 @@ void Mesh::bindVAOImplementationVAO(const GLuint id) { #else glBindVertexArrayOES #endif - (Context::current().state().mesh->currentVAO = id); + (Context::current().state().mesh.currentVAO = id); } void Mesh::bindVAO() { - GLuint& current = Context::current().state().mesh->currentVAO; + GLuint& current = Context::current().state().mesh.currentVAO; if(current != _id) { /* Binding the VAO finally creates it */ _flags |= ObjectFlag::Created; @@ -622,7 +622,7 @@ void Mesh::bindVAO() { particular, the setIndexBuffer() buffers call this function *and then* sets the _indexBuffer, which means at this point the ID will be still 0. */ - Context::current().state().buffer->bindings[Implementation::BufferState::indexForTarget(Buffer::TargetHint::ElementArray)] = _indexBuffer.id(); + Context::current().state().buffer.bindings[Implementation::BufferState::indexForTarget(Buffer::TargetHint::ElementArray)] = _indexBuffer.id(); } } @@ -731,7 +731,7 @@ void Mesh::attributePointerInternal(const Buffer& buffer, const GLuint location, void Mesh::attributePointerInternal(AttributeLayout&& attribute) { CORRADE_ASSERT(attribute.buffer.id(), "GL::Mesh::addVertexBuffer(): empty or moved-out Buffer instance was passed", ); - (this->*Context::current().state().mesh->attributePointerImplementation)(std::move(attribute)); + (this->*Context::current().state().mesh.attributePointerImplementation)(std::move(attribute)); } void Mesh::attributePointerImplementationDefault(AttributeLayout&& attribute) { @@ -775,7 +775,7 @@ void Mesh::attributePointerImplementationVAODSA(AttributeLayout&& attribute) { glVertexArrayVertexBuffer(_id, attribute.location, attribute.buffer.id(), attribute.offset, attribute.stride); if(attribute.divisor) - (this->*Context::current().state().mesh->vertexAttribDivisorImplementation)(attribute.location, attribute.divisor); + (this->*Context::current().state().mesh.vertexAttribDivisorImplementation)(attribute.location, attribute.divisor); } #ifdef CORRADE_TARGET_WINDOWS @@ -811,7 +811,7 @@ void Mesh::vertexAttribPointer(AttributeLayout& attribute) { #ifndef MAGNUM_TARGET_GLES2 glVertexAttribDivisor(attribute.location, attribute.divisor); #else - (this->*Context::current().state().mesh->vertexAttribDivisorImplementation)(attribute.location, attribute.divisor); + (this->*Context::current().state().mesh.vertexAttribDivisorImplementation)(attribute.location, attribute.divisor); #endif } } @@ -839,7 +839,7 @@ void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint #endif void Mesh::acquireVertexBuffer(Buffer&& buffer) { - (this->*Context::current().state().mesh->acquireVertexBufferImplementation)(std::move(buffer)); + (this->*Context::current().state().mesh.acquireVertexBufferImplementation)(std::move(buffer)); } void Mesh::acquireVertexBufferImplementationDefault(Buffer&& buffer) { @@ -895,7 +895,7 @@ void Mesh::unbindImplementationDefault() { #ifndef MAGNUM_TARGET_GLES2 glVertexAttribDivisor(attribute.location, 0); #else - (this->*Context::current().state().mesh->vertexAttribDivisorImplementation)(attribute.location, 0); + (this->*Context::current().state().mesh.vertexAttribDivisorImplementation)(attribute.location, 0); #endif } } diff --git a/src/Magnum/GL/MeshView.cpp b/src/Magnum/GL/MeshView.cpp index 1b16ce9d2..19c4fffc0 100644 --- a/src/Magnum/GL/MeshView.cpp +++ b/src/Magnum/GL/MeshView.cpp @@ -88,7 +88,7 @@ MeshView& MeshView::draw(AbstractShaderProgram&& shader, TransformFeedback& xfb, void MeshView::multiDrawImplementationDefault(Containers::ArrayView> meshes) { CORRADE_INTERNAL_ASSERT(meshes.size()); - const Implementation::MeshState& state = *Context::current().state().mesh; + const Implementation::MeshState& state = Context::current().state().mesh; Mesh& original = meshes.begin()->get()._original; Containers::Array count{meshes.size()}; diff --git a/src/Magnum/GL/RectangleTexture.cpp b/src/Magnum/GL/RectangleTexture.cpp index c2aa39eeb..902b83f69 100644 --- a/src/Magnum/GL/RectangleTexture.cpp +++ b/src/Magnum/GL/RectangleTexture.cpp @@ -40,7 +40,7 @@ Vector2i RectangleTexture::maxSize() { if(!Context::current().isExtensionSupported()) return {}; - GLint& value = Context::current().state().texture->maxRectangleSize; + GLint& value = Context::current().state().texture.maxRectangleSize; if(value == 0) glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, &value); diff --git a/src/Magnum/GL/Renderbuffer.cpp b/src/Magnum/GL/Renderbuffer.cpp index a9350c9f0..ae53cf779 100644 --- a/src/Magnum/GL/Renderbuffer.cpp +++ b/src/Magnum/GL/Renderbuffer.cpp @@ -37,7 +37,7 @@ namespace Magnum { namespace GL { Int Renderbuffer::maxSize() { - GLint& value = Context::current().state().framebuffer->maxRenderbufferSize; + GLint& value = Context::current().state().framebuffer.maxRenderbufferSize; /* Get the value, if not already cached */ if(value == 0) @@ -53,7 +53,7 @@ Int Renderbuffer::maxSamples() { return 0; #endif - GLint& value = Context::current().state().framebuffer->maxSamples; + GLint& value = Context::current().state().framebuffer.maxSamples; /* Get the value, if not already cached */ if(value == 0) { @@ -69,7 +69,7 @@ Int Renderbuffer::maxSamples() { #endif Renderbuffer::Renderbuffer(): _flags{ObjectFlag::DeleteOnDestruction} { - (this->*Context::current().state().framebuffer->createRenderbufferImplementation)(); + (this->*Context::current().state().framebuffer.createRenderbufferImplementation)(); } void Renderbuffer::createImplementationDefault() { @@ -88,7 +88,7 @@ Renderbuffer::~Renderbuffer() { if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; /* If bound, remove itself from state */ - GLuint& binding = Context::current().state().framebuffer->renderbufferBinding; + GLuint& binding = Context::current().state().framebuffer.renderbufferBinding; if(binding == _id) binding = 0; glDeleteRenderbuffers(1, &_id); @@ -108,28 +108,28 @@ inline void Renderbuffer::createIfNotAlready() { #ifndef MAGNUM_TARGET_WEBGL std::string Renderbuffer::label() { createIfNotAlready(); - return Context::current().state().debug->getLabelImplementation(GL_RENDERBUFFER, _id); + return Context::current().state().debug.getLabelImplementation(GL_RENDERBUFFER, _id); } Renderbuffer& Renderbuffer::setLabelInternal(const Containers::ArrayView label) { createIfNotAlready(); - Context::current().state().debug->labelImplementation(GL_RENDERBUFFER, _id, label); + Context::current().state().debug.labelImplementation(GL_RENDERBUFFER, _id, label); return *this; } #endif void Renderbuffer::setStorage(const RenderbufferFormat internalFormat, const Vector2i& size) { - (this->*Context::current().state().framebuffer->renderbufferStorageImplementation)(internalFormat, size); + (this->*Context::current().state().framebuffer.renderbufferStorageImplementation)(internalFormat, size); } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void Renderbuffer::setStorageMultisample(const Int samples, const RenderbufferFormat internalFormat, const Vector2i& size) { - (this->*Context::current().state().framebuffer->renderbufferStorageMultisampleImplementation)(samples, internalFormat, size); + (this->*Context::current().state().framebuffer.renderbufferStorageMultisampleImplementation)(samples, internalFormat, size); } #endif void Renderbuffer::bind() { - GLuint& binding = Context::current().state().framebuffer->renderbufferBinding; + GLuint& binding = Context::current().state().framebuffer.renderbufferBinding; if(binding == _id) return; diff --git a/src/Magnum/GL/Renderer.cpp b/src/Magnum/GL/Renderer.cpp index 583336b04..438f8053d 100644 --- a/src/Magnum/GL/Renderer.cpp +++ b/src/Magnum/GL/Renderer.cpp @@ -36,7 +36,7 @@ namespace Magnum { namespace GL { Range1D Renderer::lineWidthRange() { - auto& state = *Context::current().state().renderer; + Implementation::RendererState& state = Context::current().state().renderer; Range1D& value = state.lineWidthRange; /* Get the value, if not already cached */ @@ -74,11 +74,11 @@ void Renderer::setFeature(const Feature feature, const bool enabled) { #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void Renderer::enable(const Feature feature, const UnsignedInt drawBuffer) { - Context::current().state().renderer->enableiImplementation(GLenum(feature), drawBuffer); + Context::current().state().renderer.enableiImplementation(GLenum(feature), drawBuffer); } void Renderer::disable(const Feature feature, const UnsignedInt drawBuffer) { - Context::current().state().renderer->disableiImplementation(GLenum(feature), drawBuffer); + Context::current().state().renderer.disableiImplementation(GLenum(feature), drawBuffer); } void Renderer::setFeature(const Feature feature, const UnsignedInt drawBuffer, const bool enabled) { @@ -101,7 +101,7 @@ void Renderer::setClearDepth(const Double depth) { #endif void Renderer::setClearDepth(Float depth) { - Context::current().state().renderer->clearDepthfImplementation(depth); + Context::current().state().renderer.clearDepthfImplementation(depth); } void Renderer::setClearStencil(const Int stencil) { @@ -149,7 +149,7 @@ void Renderer::setPointSize(const Float size) { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void Renderer::setMinSampleShading(const Float value) { - (Context::current().state().renderer->minSampleShadingImplementation)(value); + (Context::current().state().renderer.minSampleShadingImplementation)(value); } void Renderer::minSampleShadingImplementationDefault(const GLfloat value) { @@ -173,7 +173,7 @@ UnsignedInt Renderer::maxPatchVertexCount() { return 0; #endif - GLint& value = Context::current().state().renderer->maxPatchVertexCount; + GLint& value = Context::current().state().renderer.maxPatchVertexCount; /* Get the value, if not already cached */ if(value == 0) @@ -183,7 +183,7 @@ UnsignedInt Renderer::maxPatchVertexCount() { } void Renderer::setPatchVertexCount(UnsignedInt count) { - Context::current().state().renderer->patchParameteriImplementation(GL_PATCH_VERTICES, count); + Context::current().state().renderer.patchParameteriImplementation(GL_PATCH_VERTICES, count); } #endif @@ -210,7 +210,7 @@ UnsignedInt Renderer::maxClipDistances() { return 0; #endif - GLint& value = Context::current().state().renderer->maxClipDistances; + GLint& value = Context::current().state().renderer.maxClipDistances; /* Get the value, if not already cached */ if(value == 0) @@ -238,7 +238,7 @@ UnsignedInt Renderer::maxCullDistances() { return 0; #endif - GLint& value = Context::current().state().renderer->maxCullDistances; + GLint& value = Context::current().state().renderer.maxCullDistances; /* Get the value, if not already cached */ if(value == 0) @@ -262,7 +262,7 @@ UnsignedInt Renderer::maxCombinedClipAndCullDistances() { return 0; #endif - GLint& value = Context::current().state().renderer->maxCombinedClipAndCullDistances; + GLint& value = Context::current().state().renderer.maxCombinedClipAndCullDistances; /* Get the value, if not already cached */ if(value == 0) @@ -308,7 +308,7 @@ void Renderer::setColorMask(const GLboolean allowRed, const GLboolean allowGreen #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void Renderer::setColorMask(const UnsignedInt drawBuffer, const GLboolean allowRed, const GLboolean allowGreen, const GLboolean allowBlue, const GLboolean allowAlpha) { - Context::current().state().renderer->colorMaskiImplementation(drawBuffer, allowRed, allowGreen, allowBlue, allowAlpha); + Context::current().state().renderer.colorMaskiImplementation(drawBuffer, allowRed, allowGreen, allowBlue, allowAlpha); } #endif @@ -342,19 +342,19 @@ void Renderer::setBlendFunction(const BlendFunction sourceRgb, const BlendFuncti #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) void Renderer::setBlendEquation(const UnsignedInt drawBuffer, const BlendEquation equation) { - Context::current().state().renderer->blendEquationiImplementation(drawBuffer, GLenum(equation)); + Context::current().state().renderer.blendEquationiImplementation(drawBuffer, GLenum(equation)); } void Renderer::setBlendEquation(const UnsignedInt drawBuffer, const BlendEquation rgb, const BlendEquation alpha) { - Context::current().state().renderer->blendEquationSeparateiImplementation(drawBuffer, GLenum(rgb), GLenum(alpha)); + Context::current().state().renderer.blendEquationSeparateiImplementation(drawBuffer, GLenum(rgb), GLenum(alpha)); } void Renderer::setBlendFunction(const UnsignedInt drawBuffer, const BlendFunction source, const BlendFunction destination) { - Context::current().state().renderer->blendFunciImplementation(drawBuffer, GLenum(source), GLenum(destination)); + Context::current().state().renderer.blendFunciImplementation(drawBuffer, GLenum(source), GLenum(destination)); } void Renderer::setBlendFunction(const UnsignedInt drawBuffer, const BlendFunction sourceRgb, const BlendFunction destinationRgb, const BlendFunction sourceAlpha, const BlendFunction destinationAlpha) { - Context::current().state().renderer->blendFuncSeparateiImplementation(drawBuffer, GLenum(sourceRgb), GLenum(destinationRgb), GLenum(sourceAlpha), GLenum(destinationAlpha)); + Context::current().state().renderer.blendFuncSeparateiImplementation(drawBuffer, GLenum(sourceRgb), GLenum(destinationRgb), GLenum(sourceAlpha), GLenum(destinationAlpha)); } #endif @@ -388,7 +388,7 @@ Renderer::ResetNotificationStrategy Renderer::resetNotificationStrategy() { #endif return ResetNotificationStrategy::NoResetNotification; - ResetNotificationStrategy& strategy = Context::current().state().renderer->resetNotificationStrategy; + ResetNotificationStrategy& strategy = Context::current().state().renderer.resetNotificationStrategy; if(strategy == ResetNotificationStrategy()) { #ifndef MAGNUM_TARGET_GLES @@ -402,7 +402,7 @@ Renderer::ResetNotificationStrategy Renderer::resetNotificationStrategy() { } Renderer::GraphicsResetStatus Renderer::graphicsResetStatus() { - return Context::current().state().renderer->graphicsResetStatusImplementation(); + return Context::current().state().renderer.graphicsResetStatusImplementation(); } #endif diff --git a/src/Magnum/GL/Sampler.cpp b/src/Magnum/GL/Sampler.cpp index 2120337ee..11d0c0703 100644 --- a/src/Magnum/GL/Sampler.cpp +++ b/src/Magnum/GL/Sampler.cpp @@ -107,7 +107,7 @@ SamplerWrapping samplerWrapping(const Magnum::SamplerWrapping wrapping) { } Float Sampler::maxMaxAnisotropy() { - GLfloat& value = Context::current().state().texture->maxMaxAnisotropy; + GLfloat& value = Context::current().state().texture.maxMaxAnisotropy; /* Get the value, if not already cached */ if(value == 0.0f) { diff --git a/src/Magnum/GL/Shader.cpp b/src/Magnum/GL/Shader.cpp index 046c1905d..5ac59a46e 100644 --- a/src/Magnum/GL/Shader.cpp +++ b/src/Magnum/GL/Shader.cpp @@ -113,7 +113,7 @@ constexpr bool isTypeSupported(Shader::Type) { return true; } } Int Shader::maxVertexOutputComponents() { - GLint& value = Context::current().state().shader->maxVertexOutputComponents; + GLint& value = Context::current().state().shader.maxVertexOutputComponents; /* Get the value, if not already cached */ if(value == 0) { @@ -143,7 +143,7 @@ Int Shader::maxTessellationControlInputComponents() { return 0; #endif - GLint& value = Context::current().state().shader->maxTessellationControlInputComponents; + GLint& value = Context::current().state().shader.maxTessellationControlInputComponents; /* Get the value, if not already cached */ if(value == 0) @@ -161,7 +161,7 @@ Int Shader::maxTessellationControlOutputComponents() { return 0; #endif - GLint& value = Context::current().state().shader->maxTessellationControlOutputComponents; + GLint& value = Context::current().state().shader.maxTessellationControlOutputComponents; /* Get the value, if not already cached */ if(value == 0) @@ -179,7 +179,7 @@ Int Shader::maxTessellationControlTotalOutputComponents() { return 0; #endif - GLint& value = Context::current().state().shader->maxTessellationControlTotalOutputComponents; + GLint& value = Context::current().state().shader.maxTessellationControlTotalOutputComponents; /* Get the value, if not already cached */ if(value == 0) @@ -197,7 +197,7 @@ Int Shader::maxTessellationEvaluationInputComponents() { return 0; #endif - GLint& value = Context::current().state().shader->maxTessellationEvaluationInputComponents; + GLint& value = Context::current().state().shader.maxTessellationEvaluationInputComponents; /* Get the value, if not already cached */ if(value == 0) @@ -215,7 +215,7 @@ Int Shader::maxTessellationEvaluationOutputComponents() { return 0; #endif - GLint& value = Context::current().state().shader->maxTessellationEvaluationOutputComponents; + GLint& value = Context::current().state().shader.maxTessellationEvaluationOutputComponents; /* Get the value, if not already cached */ if(value == 0) @@ -233,7 +233,7 @@ Int Shader::maxGeometryInputComponents() { return 0; #endif - GLint& value = Context::current().state().shader->maxGeometryInputComponents; + GLint& value = Context::current().state().shader.maxGeometryInputComponents; /* Get the value, if not already cached */ /** @todo The extension has only `GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB`, this is supported since GL 3.2 (wtf?) */ @@ -252,7 +252,7 @@ Int Shader::maxGeometryOutputComponents() { return 0; #endif - GLint& value = Context::current().state().shader->maxGeometryOutputComponents; + GLint& value = Context::current().state().shader.maxGeometryOutputComponents; /* Get the value, if not already cached */ /** @todo The extension has only `GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB`, this is supported since GL 3.2 (wtf?) */ @@ -271,7 +271,7 @@ Int Shader::maxGeometryTotalOutputComponents() { return 0; #endif - GLint& value = Context::current().state().shader->maxGeometryTotalOutputComponents; + GLint& value = Context::current().state().shader.maxGeometryTotalOutputComponents; /* Get the value, if not already cached */ if(value == 0) @@ -282,7 +282,7 @@ Int Shader::maxGeometryTotalOutputComponents() { #endif Int Shader::maxFragmentInputComponents() { - GLint& value = Context::current().state().shader->maxFragmentInputComponents; + GLint& value = Context::current().state().shader.maxFragmentInputComponents; /* Get the value, if not already cached */ if(value == 0) { @@ -316,7 +316,7 @@ Int Shader::maxAtomicCounterBuffers(const Type type) { } const UnsignedInt index = typeToIndex(type); - GLint& value = Context::current().state().shader->maxAtomicCounterBuffers[index]; + GLint& value = Context::current().state().shader.maxAtomicCounterBuffers[index]; /* Get the value, if not already cached */ constexpr static GLenum what[] = { @@ -341,7 +341,7 @@ Int Shader::maxCombinedAtomicCounterBuffers() { #endif return 0; - GLint& value = Context::current().state().shader->maxCombinedAtomicCounterBuffers; + GLint& value = Context::current().state().shader.maxCombinedAtomicCounterBuffers; /* Get the value, if not already cached */ if(value == 0) @@ -363,7 +363,7 @@ Int Shader::maxAtomicCounters(const Type type) { } const UnsignedInt index = typeToIndex(type); - GLint& value = Context::current().state().shader->maxAtomicCounters[index]; + GLint& value = Context::current().state().shader.maxAtomicCounters[index]; /* Get the value, if not already cached */ constexpr static GLenum what[] = { @@ -388,7 +388,7 @@ Int Shader::maxCombinedAtomicCounters() { #endif return 0; - GLint& value = Context::current().state().shader->maxCombinedAtomicCounters; + GLint& value = Context::current().state().shader.maxCombinedAtomicCounters; /* Get the value, if not already cached */ if(value == 0) @@ -410,7 +410,7 @@ Int Shader::maxImageUniforms(const Type type) { } const UnsignedInt index = typeToIndex(type); - GLint& value = Context::current().state().shader->maxImageUniforms[index]; + GLint& value = Context::current().state().shader.maxImageUniforms[index]; /* Get the value, if not already cached */ constexpr static GLenum what[] = { @@ -435,7 +435,7 @@ Int Shader::maxCombinedImageUniforms() { #endif return 0; - GLint& value = Context::current().state().shader->maxCombinedImageUniforms; + GLint& value = Context::current().state().shader.maxCombinedImageUniforms; /* Get the value, if not already cached */ if(value == 0) @@ -457,7 +457,7 @@ Int Shader::maxShaderStorageBlocks(const Type type) { } const UnsignedInt index = typeToIndex(type); - GLint& value = Context::current().state().shader->maxShaderStorageBlocks[index]; + GLint& value = Context::current().state().shader.maxShaderStorageBlocks[index]; /* Get the value, if not already cached */ constexpr static GLenum what[] = { @@ -482,7 +482,7 @@ Int Shader::maxCombinedShaderStorageBlocks() { #endif return 0; - GLint& value = Context::current().state().shader->maxCombinedShaderStorageBlocks; + GLint& value = Context::current().state().shader.maxCombinedShaderStorageBlocks; /* Get the value, if not already cached */ if(value == 0) @@ -497,7 +497,7 @@ Int Shader::maxTextureImageUnits(const Type type) { return 0; const UnsignedInt index = typeToIndex(type); - GLint& value = Context::current().state().shader->maxTextureImageUnits[index]; + GLint& value = Context::current().state().shader.maxTextureImageUnits[index]; /* Get the value, if not already cached */ constexpr static GLenum what[] = { @@ -517,7 +517,7 @@ Int Shader::maxTextureImageUnits(const Type type) { } Int Shader::maxCombinedTextureImageUnits() { - GLint& value = Context::current().state().shader->maxTextureImageUnitsCombined; + GLint& value = Context::current().state().shader.maxTextureImageUnitsCombined; /* Get the value, if not already cached */ if(value == 0) @@ -536,7 +536,7 @@ Int Shader::maxUniformBlocks(const Type type) { return 0; const UnsignedInt index = typeToIndex(type); - GLint& value = Context::current().state().shader->maxUniformBlocks[index]; + GLint& value = Context::current().state().shader.maxUniformBlocks[index]; /* Get the value, if not already cached */ constexpr static GLenum what[] = { @@ -561,7 +561,7 @@ Int Shader::maxCombinedUniformBlocks() { return 0; #endif - GLint& value = Context::current().state().shader->maxCombinedUniformBlocks; + GLint& value = Context::current().state().shader.maxCombinedUniformBlocks; /* Get the value, if not already cached */ if(value == 0) @@ -576,7 +576,7 @@ Int Shader::maxUniformComponents(const Type type) { return 0; const UnsignedInt index = typeToIndex(type); - GLint& value = Context::current().state().shader->maxUniformComponents[index]; + GLint& value = Context::current().state().shader.maxUniformComponents[index]; /* Get the value, if not already cached */ #ifndef MAGNUM_TARGET_GLES2 @@ -618,7 +618,7 @@ Int Shader::maxCombinedUniformComponents(const Type type) { return 0; const UnsignedInt index = typeToIndex(type); - GLint& value = Context::current().state().shader->maxCombinedUniformComponents[index]; + GLint& value = Context::current().state().shader.maxCombinedUniformComponents[index]; /* Get the value, if not already cached */ constexpr static GLenum what[] = { @@ -681,17 +681,17 @@ Shader::~Shader() { #ifndef MAGNUM_TARGET_WEBGL std::string Shader::label() const { #ifndef MAGNUM_TARGET_GLES2 - return Context::current().state().debug->getLabelImplementation(GL_SHADER, _id); + return Context::current().state().debug.getLabelImplementation(GL_SHADER, _id); #else - return Context::current().state().debug->getLabelImplementation(GL_SHADER_KHR, _id); + return Context::current().state().debug.getLabelImplementation(GL_SHADER_KHR, _id); #endif } Shader& Shader::setLabelInternal(const Containers::ArrayView label) { #ifndef MAGNUM_TARGET_GLES2 - Context::current().state().debug->labelImplementation(GL_SHADER, _id, label); + Context::current().state().debug.labelImplementation(GL_SHADER, _id, label); #else - Context::current().state().debug->labelImplementation(GL_SHADER_KHR, _id, label); + Context::current().state().debug.labelImplementation(GL_SHADER_KHR, _id, label); #endif return *this; } @@ -701,7 +701,7 @@ std::vector Shader::sources() const { return _sources; } Shader& Shader::addSource(std::string source) { if(!source.empty()) { - auto addSource = Context::current().state().shader->addSourceImplementation; + auto addSource = Context::current().state().shader.addSourceImplementation; /* Fix line numbers, so line 41 of third added file is marked as 3(41) in case shader version was not Version::None, because then source 0 @@ -789,7 +789,7 @@ bool Shader::compile(std::initializer_list> shader /* Some drivers are chatty and can't keep shut when there's nothing to be said, handle that as well. */ - Context::current().state().shader->cleanLogImplementation(message); + Context::current().state().shader.cleanLogImplementation(message); /* Show error log */ if(!success) { diff --git a/src/Magnum/GL/TransformFeedback.cpp b/src/Magnum/GL/TransformFeedback.cpp index 4e137d154..3b8ae5cb4 100644 --- a/src/Magnum/GL/TransformFeedback.cpp +++ b/src/Magnum/GL/TransformFeedback.cpp @@ -47,7 +47,7 @@ Int TransformFeedback::maxInterleavedComponents() { return 0; #endif - GLint& value = Context::current().state().transformFeedback->maxInterleavedComponents; + GLint& value = Context::current().state().transformFeedback.maxInterleavedComponents; if(value == 0) glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &value); @@ -61,7 +61,7 @@ Int TransformFeedback::maxSeparateAttributes() { return 0; #endif - GLint& value = Context::current().state().transformFeedback->maxSeparateAttributes; + GLint& value = Context::current().state().transformFeedback.maxSeparateAttributes; if(value == 0) glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &value); @@ -75,7 +75,7 @@ Int TransformFeedback::maxSeparateComponents() { return 0; #endif - GLint& value = Context::current().state().transformFeedback->maxSeparateComponents; + GLint& value = Context::current().state().transformFeedback.maxSeparateComponents; if(value == 0) glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &value); @@ -88,7 +88,7 @@ Int TransformFeedback::maxBuffers() { if(!Context::current().isExtensionSupported()) return maxSeparateAttributes(); - GLint& value = Context::current().state().transformFeedback->maxBuffers; + GLint& value = Context::current().state().transformFeedback.maxBuffers; if(value == 0) glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &value); @@ -100,7 +100,7 @@ Int TransformFeedback::maxVertexStreams() { if(!Context::current().isExtensionSupported()) return 1; - GLint& value = Context::current().state().transformFeedback->maxVertexStreams; + GLint& value = Context::current().state().transformFeedback.maxVertexStreams; if(value == 0) glGetIntegerv(GL_MAX_VERTEX_STREAMS, &value); @@ -110,7 +110,7 @@ Int TransformFeedback::maxVertexStreams() { #endif TransformFeedback::TransformFeedback(): _flags{ObjectFlag::DeleteOnDestruction} { - (this->*Context::current().state().transformFeedback->createImplementation)(); + (this->*Context::current().state().transformFeedback.createImplementation)(); CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding); } @@ -130,14 +130,14 @@ TransformFeedback::~TransformFeedback() { if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; /* If bound, remove itself from state */ - GLuint& binding = Context::current().state().transformFeedback->binding; + GLuint& binding = Context::current().state().transformFeedback.binding; if(binding == _id) binding = 0; glDeleteTransformFeedbacks(1, &_id); } void TransformFeedback::bindInternal() { - GLuint& bound = Context::current().state().transformFeedback->binding; + GLuint& bound = Context::current().state().transformFeedback.binding; /* Already bound, nothing to do */ if(bound == _id) return; @@ -162,23 +162,23 @@ inline void TransformFeedback::createIfNotAlready() { #ifndef MAGNUM_TARGET_WEBGL std::string TransformFeedback::label() { createIfNotAlready(); - return Context::current().state().debug->getLabelImplementation(GL_TRANSFORM_FEEDBACK, _id); + return Context::current().state().debug.getLabelImplementation(GL_TRANSFORM_FEEDBACK, _id); } TransformFeedback& TransformFeedback::setLabelInternal(const Containers::ArrayView label) { createIfNotAlready(); - Context::current().state().debug->labelImplementation(GL_TRANSFORM_FEEDBACK, _id, label); + Context::current().state().debug.labelImplementation(GL_TRANSFORM_FEEDBACK, _id, label); return *this; } #endif TransformFeedback& TransformFeedback::attachBuffer(const UnsignedInt index, Buffer& buffer, const GLintptr offset, const GLsizeiptr size) { - (this->*Context::current().state().transformFeedback->attachRangeImplementation)(index, buffer, offset, size); + (this->*Context::current().state().transformFeedback.attachRangeImplementation)(index, buffer, offset, size); return *this; } TransformFeedback& TransformFeedback::attachBuffer(const UnsignedInt index, Buffer& buffer) { - (this->*Context::current().state().transformFeedback->attachBaseImplementation)(index, buffer); + (this->*Context::current().state().transformFeedback.attachBaseImplementation)(index, buffer); return *this; } @@ -206,13 +206,13 @@ void TransformFeedback::attachImplementationDSA(const GLuint index, Buffer& buff /** @todoc const std::initializer_list makes Doxygen grumpy */ TransformFeedback& TransformFeedback::attachBuffers(const UnsignedInt firstIndex, std::initializer_list> buffers) { - (this->*Context::current().state().transformFeedback->attachRangesImplementation)(firstIndex, buffers); + (this->*Context::current().state().transformFeedback.attachRangesImplementation)(firstIndex, buffers); return *this; } /** @todoc const std::initializer_list makes Doxygen grumpy */ TransformFeedback& TransformFeedback::attachBuffers(const UnsignedInt firstIndex, std::initializer_list buffers) { - (this->*Context::current().state().transformFeedback->attachBasesImplementation)(firstIndex, buffers); + (this->*Context::current().state().transformFeedback.attachBasesImplementation)(firstIndex, buffers); return *this; } From bf802b7ad941370933271cc999c418aead013be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 26 Feb 2021 18:31:10 +0100 Subject: [PATCH 046/161] GL: put texture/image state trackers into the single allocation also. --- doc/changelog.dox | 3 ++ src/Magnum/GL/Implementation/MeshState.cpp | 4 +- src/Magnum/GL/Implementation/MeshState.h | 2 + src/Magnum/GL/Implementation/State.cpp | 42 +++++++++++++++++- src/Magnum/GL/Implementation/TextureState.cpp | 43 ++++++++----------- src/Magnum/GL/Implementation/TextureState.h | 20 ++++++--- 6 files changed, 80 insertions(+), 34 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 5f0558dec..b7b98df1f 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -186,6 +186,9 @@ See also: @subsubsection changelog-latest-changes-gl GL library +- The @ref GL::Context class got significantly optimized in terms of compile + time, header size and runtime as well, significantly reducing the amount of + allocations done at startup. - Added @ref GL::Framebuffer::Status::IncompleteDimensions for ES2. This enum isn't available on ES3 or desktop GL, but NVidia drivers are known to emit it, which is why it got added. diff --git a/src/Magnum/GL/Implementation/MeshState.cpp b/src/Magnum/GL/Implementation/MeshState.cpp index 155023482..5fdbd3378 100644 --- a/src/Magnum/GL/Implementation/MeshState.cpp +++ b/src/Magnum/GL/Implementation/MeshState.cpp @@ -405,15 +405,15 @@ MeshState::MeshState(Context& context, ContextState& contextState, Containers::S #endif } +#ifndef MAGNUM_TARGET_GLES MeshState::~MeshState() { - #ifndef MAGNUM_TARGET_GLES /* If the default VAO was created, we need to delete it to avoid leaks. Delete also the scratch VAO if the engine was so unlucky to have to run awful external GL code (it was created in Context::resetState()). */ if(defaultVAO) glDeleteVertexArrays(1, &defaultVAO); if(scratchVAO) glDeleteVertexArrays(1, &scratchVAO); - #endif } +#endif void MeshState::reset() { currentVAO = State::DisengagedBinding; diff --git a/src/Magnum/GL/Implementation/MeshState.h b/src/Magnum/GL/Implementation/MeshState.h index 13a46478b..5ed0463c2 100644 --- a/src/Magnum/GL/Implementation/MeshState.h +++ b/src/Magnum/GL/Implementation/MeshState.h @@ -33,7 +33,9 @@ struct ContextState; struct MeshState { explicit MeshState(Context& context, ContextState& contextState, Containers::StaticArrayView extensions); + #ifndef MAGNUM_TARGET_GLES ~MeshState(); + #endif void reset(); diff --git a/src/Magnum/GL/Implementation/State.cpp b/src/Magnum/GL/Implementation/State.cpp index 27d21cc55..03225464e 100644 --- a/src/Magnum/GL/Implementation/State.cpp +++ b/src/Magnum/GL/Implementation/State.cpp @@ -25,7 +25,9 @@ #include "State.h" +#include #include +#include #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" @@ -48,6 +50,26 @@ namespace Magnum { namespace GL { namespace Implementation { std::pair State::allocate(Context& context, std::ostream* const out) { + /* TextureState needs to track state per texture / image binding, fetch + how many of them is there and allocate here as well so we don't need to + do another nested allocation */ + GLint maxTextureUnits{}; + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); + CORRADE_INTERNAL_ASSERT(maxTextureUnits > 0); + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + GLint maxImageUnits{}; + #ifndef MAGNUM_TARGET_GLES + if(context.isExtensionSupported()) + #else + if(context.isVersionSupported(Version::GLES310)) + #endif + { + glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImageUnits); + CORRADE_INTERNAL_ASSERT(maxImageUnits > 0); + } + #endif + /* I have to say, the ArrayTuple is quite a crazy thing */ Containers::ArrayView stateView; Containers::ArrayView bufferStateView; @@ -62,6 +84,10 @@ std::pair State::allocate(Context& context, std: Containers::ArrayView shaderStateView; Containers::ArrayView shaderProgramStateView; Containers::ArrayView textureStateView; + Containers::ArrayView> textureBindings; + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + Containers::ArrayView> imageBindings; + #endif #ifndef MAGNUM_TARGET_GLES2 Containers::ArrayView transformFeedbackStateView; #endif @@ -79,11 +105,21 @@ std::pair State::allocate(Context& context, std: {Containers::NoInit, 1, shaderStateView}, {Containers::NoInit, 1, shaderProgramStateView}, {Containers::NoInit, 1, textureStateView}, + {Containers::ValueInit, std::size_t(maxTextureUnits), textureBindings}, + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + {Containers::ValueInit, std::size_t(maxImageUnits), imageBindings}, + #endif #ifndef MAGNUM_TARGET_GLES2 {Containers::NoInit, 1, transformFeedbackStateView} #endif }; + #ifdef MAGNUM_TARGET_GLES + /* This whole thing would be trivially destructible except for MeshState + which has to delete scratch VAOs on desktop in a custom destructor. */ + CORRADE_INTERNAL_ASSERT(!data.deleter()); + #endif + /* Extensions that might get used by current context. The State classes will set strings based on Extension::index() and then we'll go through the list and print ones that aren't null. It's 1.5 kB of temporary data @@ -120,7 +156,11 @@ std::pair State::allocate(Context& context, std: new(&state.renderer) RendererState{context, stateView.front().context, extensions}; new(&state.shader) ShaderState(context, extensions); new(&state.shaderProgram) ShaderProgramState{context, extensions}; - new(&state.texture) TextureState{context, extensions}; + new(&state.texture) TextureState{context, textureBindings, + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + imageBindings, + #endif + extensions}; #ifndef MAGNUM_TARGET_GLES2 new(&state.transformFeedback) TransformFeedbackState{context, extensions}; #endif diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index 0717b679e..4a61fa103 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -43,7 +43,13 @@ namespace Magnum { namespace GL { namespace Implementation { using namespace Containers::Literals; -TextureState::TextureState(Context& context, Containers::StaticArrayView extensions): maxSize{}, +TextureState::TextureState(Context& context, + Containers::ArrayView> bindings, + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + Containers::ArrayView> imageBindings, + #endif + Containers::StaticArrayView extensions): + maxSize{}, #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) max3DSize{}, #endif @@ -54,16 +60,22 @@ TextureState::TextureState(Context& context, Containers::StaticArrayView 0); - bindings = Containers::Array>{Containers::ValueInit, std::size_t(maxTextureUnits)}; - #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify"_s)) { CORRADE_INTERNAL_ASSERT(std::size_t(maxTextureUnits) <= decltype(bufferTextureBound)::Size); @@ -536,24 +543,8 @@ TextureState::TextureState(Context& context, Containers::StaticArrayView()) - #else - if(context.isVersionSupported(Version::GLES310)) - #endif - { - GLint maxImageUnits; - glGetIntegerv(GL_MAX_IMAGE_UNITS, &maxImageUnits); - imageBindings = Containers::Array>{Containers::ValueInit, std::size_t(maxImageUnits)}; - } - #endif } -TextureState::~TextureState() = default; - void TextureState::reset() { std::fill_n(bindings.begin(), bindings.size(), std::pair{{}, State::DisengagedBinding}); #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) diff --git a/src/Magnum/GL/Implementation/TextureState.h b/src/Magnum/GL/Implementation/TextureState.h index f36f76811..fcb22b91e 100644 --- a/src/Magnum/GL/Implementation/TextureState.h +++ b/src/Magnum/GL/Implementation/TextureState.h @@ -25,7 +25,7 @@ DEALINGS IN THE SOFTWARE. */ -#include +#include #include #include "Magnum/Magnum.h" @@ -51,8 +51,12 @@ namespace Magnum { namespace GL { namespace Implementation { struct TextureState { - explicit TextureState(Context& context, Containers::StaticArrayView extensions); - ~TextureState(); + explicit TextureState(Context& context, + Containers::ArrayView> bindings, + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + Containers::ArrayView> imageBindings, + #endif + Containers::StaticArrayView extensions); void reset(); @@ -155,13 +159,19 @@ struct TextureState { GLint bufferOffsetAlignment; #endif - Containers::Array> bindings; + /* These arrays get allocated in State in a single allocation and views to + them are passed here via the constructor. */ + + /* Texture type, texture object ID. While not true, for simplicity this + assumes that each slot can have just one ID bound, not one ID per + texture type. */ + Containers::ArrayView> bindings; #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) Math::BoolVector<80> bufferTextureBound; #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) /* Texture object ID, level, layered, layer, access */ - Containers::Array> imageBindings; + Containers::ArrayView> imageBindings; #endif }; From 1c66807e101280d6129e74c087b365b50597a550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 27 Feb 2021 11:43:48 +0100 Subject: [PATCH 047/161] Platform: explicitly override Configuration::Flags in all apps. These will become a subset of what GL::Context::Configuration::Flag provides and so can't just inherit the enum anymore. --- src/Magnum/Platform/AbstractXApplication.h | 89 ++++++++++++++++--- src/Magnum/Platform/AndroidApplication.h | 89 ++++++++++++++++--- .../Platform/WindowlessCglApplication.h | 89 ++++++++++++++++--- .../Platform/WindowlessIosApplication.h | 76 ++++++++++++++-- 4 files changed, 301 insertions(+), 42 deletions(-) diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index e5e60c322..fc91893a4 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -340,32 +340,97 @@ Double-buffered OpenGL context. */ class AbstractXApplication::GLConfiguration: public GL::Context::Configuration { public: + /** + * @brief Context flag + * + * Includes also everything from @ref GL::Context::Configuration::Flag. + * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag + */ + enum class Flag: UnsignedLong { + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + }; + + /** + * @brief Context flags + * + * @see @ref setFlags(), @ref Context::Flags + */ + typedef Containers::EnumSet Flags; + explicit GLConfiguration(); ~GLConfiguration(); - /** @copydoc Sdl2Application::GLConfiguration::version() */ - GL::Version version() const { return _version; } - - /** @copydoc Sdl2Application::GLConfiguration::setVersion() */ - GLConfiguration& setVersion(GL::Version version) { - _version = version; - return *this; + /** @brief Context flags */ + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); } - /* Overloads to remove WTF-factor from method chaining order */ - #ifndef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. To avoid clearing default flags by accident, + * prefer to use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() + */ GLConfiguration& setFlags(Flags flags) { - GL::Context::Configuration::setFlags(flags); + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } + + /** + * @brief Add context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearFlags() + */ GLConfiguration& addFlags(Flags flags) { - GL::Context::Configuration::addFlags(flags); + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } + + /** + * @brief Clear context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing + * instead of replacing them. Useful for removing default flags. + * @see @ref addFlags() + */ GLConfiguration& clearFlags(Flags flags) { - GL::Context::Configuration::clearFlags(flags); + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); + return *this; + } + + /** @copydoc Sdl2Application::GLConfiguration::version() */ + GL::Version version() const { return _version; } + + /** @copydoc Sdl2Application::GLConfiguration::setVersion() */ + GLConfiguration& setVersion(GL::Version version) { + _version = version; return *this; } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration) #endif diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 6d00d55c0..d6055afad 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -453,8 +453,85 @@ Double-buffered RGBA canvas with depth and stencil buffers. */ class AndroidApplication::GLConfiguration: public GL::Context::Configuration { public: + /** + * @brief Context flag + * + * Includes also everything from @ref GL::Context::Configuration::Flag. + * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag + */ + enum class Flag: UnsignedLong { + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + }; + + /** + * @brief Context flags + * + * @see @ref setFlags(), @ref Context::Flags + */ + typedef Containers::EnumSet Flags; + /*implicit*/ GLConfiguration(); + /** @brief Context flags */ + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. To avoid clearing default flags by accident, + * prefer to use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() + */ + GLConfiguration& setFlags(Flags flags) { + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); + return *this; + } + + /** + * @brief Add context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearFlags() + */ + GLConfiguration& addFlags(Flags flags) { + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); + return *this; + } + + /** + * @brief Clear context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing + * instead of replacing them. Useful for removing default flags. + * @see @ref addFlags() + */ + GLConfiguration& clearFlags(Flags flags) { + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); + return *this; + } + /** * @brief Set context version * @@ -509,18 +586,6 @@ class AndroidApplication::GLConfiguration: public GL::Context::Configuration { /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT - GLConfiguration& setFlags(Flags flags) { - GL::Context::Configuration::setFlags(flags); - return *this; - } - GLConfiguration& addFlags(Flags flags) { - GL::Context::Configuration::addFlags(flags); - return *this; - } - GLConfiguration& clearFlags(Flags flags) { - GL::Context::Configuration::clearFlags(flags); - return *this; - } MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(GLConfiguration) #endif diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index a8f58a46d..20f8d8fda 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -163,6 +163,83 @@ class WindowlessCglContext { */ class WindowlessCglContext::Configuration: public GL::Context::Configuration { public: + /** + * @brief Context flag + * + * Includes also everything from @ref GL::Context::Configuration::Flag. + * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag + */ + enum class Flag: UnsignedLong { + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + }; + + /** + * @brief Context flags + * + * @see @ref setFlags(), @ref Context::Flags + */ + typedef Containers::EnumSet Flags; + + /** @brief Context flags */ + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. To avoid clearing default flags by accident, + * prefer to use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() + */ + Configuration& setFlags(Flags flags) { + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); + return *this; + } + + /** + * @brief Add context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearFlags() + */ + Configuration& addFlags(Flags flags) { + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); + return *this; + } + + /** + * @brief Clear context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing + * instead of replacing them. Useful for removing default flags. + * @see @ref addFlags() + */ + Configuration& clearFlags(Flags flags) { + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); + return *this; + } + /** * @brief Create a shared context * @return Reference to self (for method chaining) @@ -189,18 +266,6 @@ class WindowlessCglContext::Configuration: public GL::Context::Configuration { /* Overloads to remove WTF-factor from method chaining order */ #ifndef DOXYGEN_GENERATING_OUTPUT - Configuration& setFlags(Flags flags) { - GL::Context::Configuration::setFlags(flags); - return *this; - } - Configuration& addFlags(Flags flags) { - GL::Context::Configuration::addFlags(flags); - return *this; - } - Configuration& clearFlags(Flags flags) { - GL::Context::Configuration::clearFlags(flags); - return *this; - } MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration) #endif diff --git a/src/Magnum/Platform/WindowlessIosApplication.h b/src/Magnum/Platform/WindowlessIosApplication.h index d02e92b07..472e6d92f 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.h +++ b/src/Magnum/Platform/WindowlessIosApplication.h @@ -154,23 +154,87 @@ class WindowlessIosContext { */ class WindowlessIosContext::Configuration: public GL::Context::Configuration { public: - /* Overloads to remove WTF-factor from method chaining order */ - #ifndef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Context flag + * + * Includes also everything from @ref GL::Context::Configuration::Flag. + * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag + */ + enum class Flag: UnsignedLong { + /** + * @copydoc GL::Context::Configuration::Flag::QuietLog + * @m_since_latest + */ + QuietLog = UnsignedLong(GL::Context::Configuration::Flag::QuietLog), + + /** + * @copydoc GL::Context::Configuration::Flag::VerboseLog + * @m_since_latest + */ + VerboseLog = UnsignedLong(GL::Context::Configuration::Flag::VerboseLog), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidation + * @m_since_latest + */ + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + }; + + /** + * @brief Context flags + * + * @see @ref setFlags(), @ref Context::Flags + */ + typedef Containers::EnumSet Flags; + + /** @brief Context flags */ + Flags flags() const { + return Flag(UnsignedLong(GL::Context::Configuration::flags())); + } + + /** + * @brief Set context flags + * @return Reference to self (for method chaining) + * + * Default is no flag. To avoid clearing default flags by accident, + * prefer to use @ref addFlags() and @ref clearFlags() instead. + * @see @ref GL::Context::flags() + */ Configuration& setFlags(Flags flags) { - GL::Context::Configuration::setFlags(flags); + GL::Context::Configuration::setFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } + + /** + * @brief Add context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ORs the flags with existing instead of + * replacing them. Useful for preserving the defaults. + * @see @ref clearFlags() + */ Configuration& addFlags(Flags flags) { - GL::Context::Configuration::addFlags(flags); + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } + + /** + * @brief Clear context flags + * @return Reference to self (for method chaining) + * + * Unlike @ref setFlags(), ANDs the inverse of @p flags with existing + * instead of replacing them. Useful for removing default flags. + * @see @ref addFlags() + */ Configuration& clearFlags(Flags flags) { - GL::Context::Configuration::clearFlags(flags); + GL::Context::Configuration::clearFlags(GL::Context::Configuration::Flag(UnsignedLong(flags))); return *this; } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT MAGNUM_GL_CONTEXT_CONFIGURATION_SUBCLASS_IMPLEMENTATION(Configuration) #endif - }; /** From 46df57f6d551d0961477b2e0192b5cb391401150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 27 Feb 2021 11:46:43 +0100 Subject: [PATCH 048/161] GL,Platform: introduce GL::Context::Configuration::Flag::Windowless. With this flag set (which is done implicitly for all windowless apps and, conversely, not done for all windowed apps), the default framebuffer state isn't touched in any way, which should avoid potential race conditions with default framebuffer on another thread. --- doc/changelog.dox | 7 +++++++ src/Magnum/GL/Context.cpp | 12 ++++++++++-- src/Magnum/GL/Context.h | 14 ++++++++++++++ src/Magnum/GL/Framebuffer.cpp | 19 ++++++++++++------- src/Magnum/Platform/AbstractXApplication.h | 4 +++- src/Magnum/Platform/AndroidApplication.h | 4 +++- src/Magnum/Platform/EmscriptenApplication.h | 4 +++- src/Magnum/Platform/GlfwApplication.h | 4 +++- src/Magnum/Platform/Sdl2Application.h | 4 +++- .../Platform/WindowlessCglApplication.cpp | 4 ++++ .../Platform/WindowlessCglApplication.h | 6 +++++- .../Platform/WindowlessEglApplication.cpp | 1 + .../Platform/WindowlessEglApplication.h | 4 +++- .../Platform/WindowlessGlxApplication.cpp | 1 + .../Platform/WindowlessGlxApplication.h | 4 +++- .../Platform/WindowlessIosApplication.h | 6 +++++- .../Platform/WindowlessIosApplication.mm | 4 ++++ .../Platform/WindowlessWglApplication.cpp | 1 + .../Platform/WindowlessWglApplication.h | 4 +++- .../WindowlessWindowsEglApplication.cpp | 4 ++++ .../WindowlessWindowsEglApplication.h | 6 +++++- 21 files changed, 97 insertions(+), 20 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index b7b98df1f..eaed80ba0 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -196,6 +196,13 @@ See also: now advertised as a @cpp "intel-windows-chatty-shader-compiler" @ce workaround, instead of being done silently. See @ref opengl-workarounds for more information. +- @ref Platform::WindowlessEglApplication "Platform::Windowless*Application" + instances no longer touch default framebuffer state in order to avoid + potential race conditions with a windowed context on another thread. This + is also exposed via a new @ref GL::Context::Configuration::Flag::Windowless + flag for integration with custom-created OpenGL contexts. See also + [mosra/magnum#493](https://github.com/mosra/magnum/pull/493) and + [mosra/magnum#494](https://github.com/mosra/magnum/pull/494). @subsubsection changelog-latest-changes-math Math library diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 288a837b9..d1069ac8c 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -785,6 +785,10 @@ bool Context::tryCreate(const Configuration& configuration) { if(configuration.flags() & Configuration::Flag::GpuValidation) _configurationFlags |= Configuration::Flag::GpuValidation; + /* Same for windowless */ + if(configuration.flags() & Configuration::Flag::Windowless) + _configurationFlags |= Configuration::Flag::Windowless; + /* Driver workarounds get merged. Not using disableDriverWorkaround() here since the Configuration already contains the internal string views. */ for(const Containers::StringView workaround: configuration.disabledWorkarounds()) @@ -974,9 +978,13 @@ bool Context::tryCreate(const Configuration& configuration) { if(!workaround.second) Debug(output) << " " << workaround.first; } - /* Initialize functionality based on current OpenGL version and extensions */ /** @todo Get rid of these */ - DefaultFramebuffer::initializeContextBasedFunctionality(*this); + /* Initialize functionality based on current OpenGL version and extensions. + If we are on a windowless context don't touch the default framebuffer + to avoid potential race conditions with default framebuffer on another + thread. */ + if(!(_configurationFlags & Configuration::Flag::Windowless)) + DefaultFramebuffer::initializeContextBasedFunctionality(*this); Renderer::initializeContextBasedFunctionality(); /* Enable GPU validation, if requested */ diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 9d38e146a..86a6763ed 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -70,6 +70,7 @@ namespace Implementation { Context before the Configuration class is defined, it has to be here */ enum class ContextConfigurationFlag: UnsignedLong { /* Keeping the 32-bit range reserved for actual GL context flags */ + Windowless = 1ull << 60, QuietLog = 1ull << 61, VerboseLog = 1ull << 62, GpuValidation = 1ull << 63 @@ -914,6 +915,19 @@ class MAGNUM_GL_EXPORT Context::Configuration { /* Docs only, keep in sync with Implementation::ContextConfigurationFlag please */ + /** + * Treat the context as windowless, assume there's no default + * framebuffer and thus don't touch @ref defaultFramebuffer in any + * way. Useful for preventing race conditions when creating OpenGL + * contexts in background threads. + * + * This flag is implicitly enabled in all + * @ref Platform::WindowlessEglContext::Configuration "Platform::Windowless*Application::Configuration", + * and, conversely, not possible to enable in any + * @ref Platform::Sdl2Application::GLConfiguration::Flag "Platform::*Application::GLConfiguration". + */ + Windowless = 1ull << 60, + /** * Print only warnings and errors instead of the usual startup log * listing used extensions and workarounds. Ignored if diff --git a/src/Magnum/GL/Framebuffer.cpp b/src/Magnum/GL/Framebuffer.cpp index 135534bdf..e1edba78a 100644 --- a/src/Magnum/GL/Framebuffer.cpp +++ b/src/Magnum/GL/Framebuffer.cpp @@ -120,18 +120,23 @@ Framebuffer::~Framebuffer() { if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return; /* If bound, remove itself from state */ - Implementation::FramebufferState& state = Context::current().state().framebuffer; + Context& context = Context::current(); + Implementation::FramebufferState& state = context.state().framebuffer; if(state.readBinding == _id) state.readBinding = 0; - /* For draw binding reset also viewport */ + /* For draw binding reset also viewport. Don't do that for windowless + contexts to avoid potential race conditions with default framebuffer on + another thread. */ if(state.drawBinding == _id) { state.drawBinding = 0; - /** - * @todo Less ugly solution (need to call setViewportInternal() to - * reset the viewport to size of default framebuffer) - */ - defaultFramebuffer.bind(); + if(!(context.configurationFlags() & Context::Configuration::Flag::Windowless)) { + /** + * @todo Less ugly solution (need to call setViewportInternal() to + * reset the viewport to size of default framebuffer) + */ + defaultFramebuffer.bind(); + } } glDeleteFramebuffers(1, &_id); diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index fc91893a4..3b02f92f7 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -343,7 +343,9 @@ class AbstractXApplication::GLConfiguration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is not meant to be enabled for windowed apps. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index d6055afad..11ea3d620 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -456,7 +456,9 @@ class AndroidApplication::GLConfiguration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is not meant to be enabled for windowed apps. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index 585c24af1..fd76e5867 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -942,7 +942,9 @@ class EmscriptenApplication::GLConfiguration: public GL::Context::Configuration /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is not meant to be enabled for windowed apps. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 2d27a7180..c4f491665 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -784,7 +784,9 @@ class GlfwApplication::GLConfiguration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is not meant to be enabled for windowed apps. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index acb6279be..4963f0a7f 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -1236,7 +1236,9 @@ class Sdl2Application::GLConfiguration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is not meant to be enabled for windowed apps. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { diff --git a/src/Magnum/Platform/WindowlessCglApplication.cpp b/src/Magnum/Platform/WindowlessCglApplication.cpp index 146780ab7..ed8efa5d4 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.cpp +++ b/src/Magnum/Platform/WindowlessCglApplication.cpp @@ -105,6 +105,10 @@ bool WindowlessCglContext::release() { return false; } +WindowlessCglContext::Configuration::Configuration() { + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless); +} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessCglApplication::WindowlessCglApplication(const Arguments& arguments): WindowlessCglApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index 20f8d8fda..ecb3dc915 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -166,7 +166,9 @@ class WindowlessCglContext::Configuration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is enabled implicitly by default. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { @@ -196,6 +198,8 @@ class WindowlessCglContext::Configuration: public GL::Context::Configuration { */ typedef Containers::EnumSet Flags; + /*implicit*/ Configuration(); + /** @brief Context flags */ Flags flags() const { return Flag(UnsignedLong(GL::Context::Configuration::flags())); diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 9b8e3547b..347ef34d7 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -533,6 +533,7 @@ WindowlessEglContext::Configuration::Configuration() : _device{} #endif { + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless); #ifndef MAGNUM_TARGET_GLES addFlags(Flag::ForwardCompatible); #endif diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index 6dbd46279..ecbe7c116 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -183,7 +183,9 @@ class WindowlessEglContext::Configuration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is enabled implicitly by default. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index 0d0cb3fb4..01bea105a 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -274,6 +274,7 @@ bool WindowlessGlxContext::release() { } WindowlessGlxContext::Configuration::Configuration() { + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless); #ifndef MAGNUM_TARGET_GLES addFlags(Flag::ForwardCompatible); #endif diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 639625be5..158f19edf 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -188,7 +188,9 @@ class WindowlessGlxContext::Configuration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is enabled implicitly by default. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { diff --git a/src/Magnum/Platform/WindowlessIosApplication.h b/src/Magnum/Platform/WindowlessIosApplication.h index 472e6d92f..5b55b2643 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.h +++ b/src/Magnum/Platform/WindowlessIosApplication.h @@ -157,7 +157,9 @@ class WindowlessIosContext::Configuration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is enabled implicitly by default. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { @@ -187,6 +189,8 @@ class WindowlessIosContext::Configuration: public GL::Context::Configuration { */ typedef Containers::EnumSet Flags; + /*implicit*/ Configuration(); + /** @brief Context flags */ Flags flags() const { return Flag(UnsignedLong(GL::Context::Configuration::flags())); diff --git a/src/Magnum/Platform/WindowlessIosApplication.mm b/src/Magnum/Platform/WindowlessIosApplication.mm index a174de8e2..c3778778f 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.mm +++ b/src/Magnum/Platform/WindowlessIosApplication.mm @@ -82,6 +82,10 @@ bool WindowlessIosContext::release() { return false; } +WindowlessIosContext::Configuration::Configuration() { + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless); +} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessIosApplication::WindowlessIosApplication(const Arguments& arguments): WindowlessIosApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 5f9482f3c..493e94b26 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -259,6 +259,7 @@ bool WindowlessWglContext::release() { } WindowlessWglContext::Configuration::Configuration() { + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless); #ifndef MAGNUM_TARGET_GLES addFlags(Flag::ForwardCompatible); #endif diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 71db719f2..067369fcc 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -175,7 +175,9 @@ class WindowlessWglContext::Configuration: public GL::Context::Configuration { /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is enabled implicitly by default. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index b153ac85d..5eac49ebe 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -182,6 +182,10 @@ bool WindowlessWindowsEglContext::release() { return false; } +WindowlessWindowsEglContext::Configuration::Configuration() { + GL::Context::Configuration::addFlags(GL::Context::Configuration::Flag::Windowless); +} + #ifndef DOXYGEN_GENERATING_OUTPUT WindowlessWindowsEglApplication::WindowlessWindowsEglApplication(const Arguments& arguments): WindowlessWindowsEglApplication{arguments, Configuration{}} {} #endif diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 64c4701bc..7268ad2b8 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -161,7 +161,9 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat /** * @brief Context flag * - * Includes also everything from @ref GL::Context::Configuration::Flag. + * Includes also everything from @ref GL::Context::Configuration::Flag + * except for @relativeref{GL::Context::Configuration,Flag::Windowless}, + * which is enabled implicitly by default. * @see @ref Flags, @ref setFlags(), @ref GL::Context::Flag */ enum class Flag: UnsignedLong { @@ -199,6 +201,8 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat */ typedef Containers::EnumSet Flags; + /*implicit*/ Configuration(); + /** @brief Context flags */ Flags flags() const { return Flag(UnsignedLong(GL::Context::Configuration::flags())); From 13fc4ebffa2d87844d8802b84a42acceac0810e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 27 Feb 2021 14:26:58 +0100 Subject: [PATCH 049/161] Platform: suggest EXCLUDE_FROM_ALL for a GLFW CMake subproject. --- src/Magnum/Platform/GlfwApplication.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index c4f491665..85fd42770 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -116,7 +116,7 @@ the first part and point `CMAKE_PREFIX_PATH` to its installation dir if necessary. @code{.cmake} -add_subdirectory(glfw) +add_subdirectory(glfw EXCLUDE_FROM_ALL) set(WITH_GLFWAPPLICATION ON CACHE BOOL "" FORCE) add_subdirectory(magnum EXCLUDE_FROM_ALL) From d9f16f30d7225b230afcc2c1bf4ef9eb57a9acc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 1 Mar 2021 16:23:24 +0100 Subject: [PATCH 050/161] Platform: adapt the SwiftShader EGL workaround to recent changes. The 64-bit flags are now always non-empty in WindowlessEglApplication (containing the Windowless flag), so we should slice to 32-bit and check that instead. --- src/Magnum/Platform/WindowlessEglApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 347ef34d7..36adfadb0 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -352,7 +352,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G a zero value, so erase these. It also doesn't handle them as correct flags, but instead checks for the whole value, so a combination won't work either: https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L8104 */ - if(!configuration.flags() && version && std::strstr(version, "SwiftShader") != nullptr && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) { + if(!(UnsignedLong(flags) & 0xffffffffu) && version && std::strstr(version, "SwiftShader") != nullptr && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) { auto& contextFlags = attributes[Containers::arraySize(attributes) - 3]; CORRADE_INTERNAL_ASSERT(contextFlags == EGL_CONTEXT_FLAGS_KHR); contextFlags = EGL_NONE; From d1774ef4d2f747230b8bae088506e68dade502a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 1 Mar 2021 17:37:14 +0100 Subject: [PATCH 051/161] Platform: replace UGLY error-prone C string handling with StringViews. We no longer have to use sizeof("...") to avoid useless strlen calls or check for nulls because the StringView APIs are ACTUALLY SANE and not a full of nasty surprises and performance / security pitfalls like with both the C and C++ standard library functions. Good riddance. --- src/Magnum/Platform/GlfwApplication.cpp | 27 ++++++------------- src/Magnum/Platform/Sdl2Application.cpp | 22 +++++---------- .../Platform/WindowlessEglApplication.cpp | 24 ++++++++--------- .../Platform/WindowlessGlxApplication.cpp | 14 +++------- .../Platform/WindowlessWglApplication.cpp | 17 ++++-------- 5 files changed, 35 insertions(+), 69 deletions(-) diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 5e51f14ac..1527651d2 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -28,7 +28,6 @@ #include "GlfwApplication.h" -#include #include #include #include @@ -498,9 +497,7 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf succeeds, make the context current so we can query GL_VENDOR below. If we are on Wayland, this is causing a segfault; a blinking window is acceptable in this case. */ - constexpr const char waylandString[] = "wayland"; - const char* const xdgSessionType = std::getenv("XDG_SESSION_TYPE"); - if(!xdgSessionType || std::strncmp(xdgSessionType, waylandString, sizeof(waylandString)) != 0) + if(std::getenv("XDG_SESSION_TYPE") != "wayland"_s) glfwWindowHint(GLFW_VISIBLE, false); else if(_verboseLog) Warning{} << "Platform::GlfwApplication: Wayland detected, GL context has to be created with the window visible and may cause flicker on startup"; @@ -515,27 +512,19 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf version, they force the version to the one specified, which is completely useless behavior. */ #ifndef CORRADE_TARGET_APPLE - constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; - #ifdef CORRADE_TARGET_WINDOWS - constexpr static const char intelVendorString[] = "Intel"; - #endif - constexpr static const char amdVendorString[] = "ATI Technologies Inc."; - const char* vendorString; + Containers::StringView vendorString; #endif if(glConfiguration.version() == GL::Version::None && (!_window #ifndef CORRADE_TARGET_APPLE - /* If context creation fails *really bad*, glGetString() may actually - return nullptr. Check for that to avoid crashes deep inside - strncmp(). Sorry about the UGLY code, HOPEFULLY THERE WON'T BE MORE - WORKAROUNDS */ + /* Sorry about the UGLY code, HOPEFULLY THERE WON'T BE MORE WORKAROUNDS */ || (vendorString = reinterpret_cast(glGetString(GL_VENDOR)), - vendorString && (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || + (vendorString == "NVIDIA Corporation"_s || #ifdef CORRADE_TARGET_WINDOWS - std::strncmp(vendorString, intelVendorString, sizeof(intelVendorString)) == 0 || - #endif - std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) - && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s)) + vendorString == "Intel"_s || #endif + vendorString == "ATI Technologies Inc."_s) + && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s)) + #endif )) { /* Don't print any warning when doing the workaround, because the bug will be there probably forever */ diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 3b815f653..1552d9afc 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -26,7 +26,7 @@ #include "Sdl2Application.h" -#include +#include /** @todo remove, needed for std::strlen() in TextInputEvent */ #ifdef CORRADE_TARGET_CLANG_CL /* SDL does #pragma pack(push,8) and #pragma pack(pop,8) in different headers (begin_code.h and end_code.h) and clang-cl doesn't like that, even though it @@ -545,26 +545,18 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf version, they force the version to the one specified, which is completely useless behavior. */ #ifndef CORRADE_TARGET_APPLE - constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; - #ifdef CORRADE_TARGET_WINDOWS - constexpr static const char intelVendorString[] = "Intel"; - #endif - constexpr static const char amdVendorString[] = "ATI Technologies Inc."; - const char* vendorString; + Containers::StringView vendorString; #endif if(glConfiguration.version() == GL::Version::None && (!_glContext #ifndef CORRADE_TARGET_APPLE - /* If context creation fails *really bad*, glGetString() may actually - return nullptr. Check for that to avoid crashes deep inside - strncmp(). Sorry about the UGLY code, HOPEFULLY THERE WON'T BE MORE - WORKAROUNDS */ + /* Sorry about the UGLY code, HOPEFULLY THERE WON'T BE MORE WORKAROUNDS */ || (vendorString = reinterpret_cast(glGetString(GL_VENDOR)), - vendorString && (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || + (vendorString == "NVIDIA Corporation"_s || #ifdef CORRADE_TARGET_WINDOWS - std::strncmp(vendorString, intelVendorString, sizeof(intelVendorString)) == 0 || + vendorString == "Intel"_s || #endif - std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) - && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s)) + vendorString == "ATI Technologies Inc."_s) + && !_context->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s)) #endif )) { /* Don't print any warning when doing the workaround, because the bug diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 36adfadb0..dbcf71e64 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -27,7 +27,7 @@ #include "WindowlessEglApplication.h" -#include +#include /** @todo used by extensionSupported(), cleann up */ #include #include #include @@ -346,13 +346,13 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G #endif #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) - const char* version = eglQueryString(_display, EGL_VERSION); + const Containers::StringView version = eglQueryString(_display, EGL_VERSION); /* SwiftShader 3.3.0.1 blows up on encountering EGL_CONTEXT_FLAGS_KHR with a zero value, so erase these. It also doesn't handle them as correct flags, but instead checks for the whole value, so a combination won't work either: https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L8104 */ - if(!(UnsignedLong(flags) & 0xffffffffu) && version && std::strstr(version, "SwiftShader") != nullptr && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) { + if(!(UnsignedLong(flags) & 0xffffffffu) && version.contains("SwiftShader"_s) && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) { auto& contextFlags = attributes[Containers::arraySize(attributes) - 3]; CORRADE_INTERNAL_ASSERT(contextFlags == EGL_CONTEXT_FLAGS_KHR); contextFlags = EGL_NONE; @@ -401,15 +401,13 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G /* The workaround check is the last so it doesn't appear in workaround list on unrelated drivers */ - constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; - constexpr static const char amdVendorString[] = "ATI Technologies Inc."; - const char* const vendorString = reinterpret_cast(glGetString(GL_VENDOR)); - /* If context creation fails *really bad*, glGetString() may actually - return nullptr. Check for that to avoid crashes deep inside - strncmp() */ - if(vendorString && (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || - std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && - (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) + const Containers::StringView vendorString = reinterpret_cast(glGetString(GL_VENDOR)); + /* Unlike GLFW/SDL2/WGL there's no Intel here because EGL doesn't work + with native drivers on Windows, only though ANGLE etc, and those + don't suffer from this issue. */ + if((vendorString == "NVIDIA Corporation"_s || + vendorString == "ATI Technologies Inc."_s) + && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) { /* Destroy the core context and create a compatibility one */ eglDestroyContext(_display, _context); @@ -442,7 +440,7 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) /* SwiftShader 3.3.0.1 needs some pbuffer, otherwise it crashes somewhere deep inside when making the context current */ - if(version && std::strstr(version, "SwiftShader") != nullptr && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-egl-context-needs-pbuffer"_s))) { + if(version.contains("SwiftShader"_s) && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-egl-context-needs-pbuffer"_s))) { EGLint surfaceAttributes[] = { EGL_WIDTH, 32, EGL_HEIGHT, 32, diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index 01bea105a..71e3e07db 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -26,7 +26,6 @@ #include "WindowlessGlxApplication.h" -#include #include #include #include @@ -186,15 +185,10 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura /* The workaround check is the last so it doesn't appear in workaround list on unrelated drivers */ - constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; - constexpr static const char amdVendorString[] = "ATI Technologies Inc."; - const char* const vendorString = reinterpret_cast(glGetString(GL_VENDOR)); - /* If context creation fails *really bad*, glGetString() may actually - return nullptr. Check for that to avoid crashes deep inside - strncmp() */ - if(vendorString && (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || - std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && - (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) + const Containers::StringView vendorString = reinterpret_cast(glGetString(GL_VENDOR)); + if((vendorString == "NVIDIA Corporation"_s || + vendorString == "ATI Technologies Inc."_s) + && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) { /* Destroy the core context and create a compatibility one */ glXDestroyContext(_display, _context); diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 493e94b26..13ad08dc5 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -25,7 +25,6 @@ #include "WindowlessWglApplication.h" -#include #include #include #include @@ -183,17 +182,11 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G /* The workaround check is the last so it doesn't appear in workaround list on unrelated drivers */ - constexpr static const char nvidiaVendorString[] = "NVIDIA Corporation"; - constexpr static const char intelVendorString[] = "Intel"; - constexpr static const char amdVendorString[] = "ATI Technologies Inc."; - const char* const vendorString = reinterpret_cast(glGetString(GL_VENDOR)); - /* If context creation fails *really bad*, glGetString() may actually - return nullptr. Check for that to avoid crashes deep inside - strncmp() */ - if(vendorString && (std::strncmp(vendorString, nvidiaVendorString, sizeof(nvidiaVendorString)) == 0 || - std::strncmp(vendorString, intelVendorString, sizeof(intelVendorString)) == 0 || - std::strncmp(vendorString, amdVendorString, sizeof(amdVendorString)) == 0) && - (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) + const Containers::StringView vendorString = reinterpret_cast(glGetString(GL_VENDOR)); + if((vendorString == "NVIDIA Corporation"_s || + vendorString == "Intel"_s || + vendorString == "ATI Technologies Inc."_s) + && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("no-forward-compatible-core-context"_s))) { /* Destroy the core context and create a compatibility one */ wglDeleteContext(_context); From 24138e2c604288b33e2587bf9ae235324f57e9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 1 Mar 2021 19:49:01 +0100 Subject: [PATCH 052/161] Platform: implement [GL]Configuration::Flag::NoError in all apps. Except CGL, iOS, AndroidApplication and AbstractXApplication which are either too crappy or don't have the needed scaffolding for specifying context flags yet. --- doc/changelog.dox | 6 ++ src/Magnum/Platform/GlfwApplication.h | 6 +- src/Magnum/Platform/Sdl2Application.cpp | 4 + src/Magnum/Platform/Sdl2Application.h | 15 ++++ .../Platform/WindowlessEglApplication.cpp | 88 ++++++++++++++----- .../Platform/WindowlessEglApplication.h | 11 +++ .../Platform/WindowlessGlxApplication.cpp | 53 ++++++++++- .../Platform/WindowlessGlxApplication.h | 10 +++ .../Platform/WindowlessWglApplication.cpp | 54 +++++++++++- .../Platform/WindowlessWglApplication.h | 10 +++ .../WindowlessWindowsEglApplication.cpp | 20 ++++- .../WindowlessWindowsEglApplication.h | 10 +++ 12 files changed, 256 insertions(+), 31 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index eaed80ba0..1db6285c2 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -119,6 +119,12 @@ See also: to all @cpp Platform::Windowless*Context @ce classes. Useful for transferring OpenGL contexts between threads, see also [mosra/magnum#495](https://github.com/mosra/magnum/pull/495). +- Implemented @relativeref{Platform::WindowlessEglApplication,Configuration::Flag::NoError} + in @ref Platform::WindowlessEglApplication, + @ref Platform::WindowlessGlxApplication, + @ref Platform::WindowlessWglApplication, + @ref Platform::WindowlessWindowsEglApplication and + @ref Platform::Sdl2Application @subsubsection changelog-latest-new-shaders Shaders library diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 85fd42770..327511c4c 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -802,9 +802,9 @@ class GlfwApplication::GLConfiguration: public GL::Context::Configuration { #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(GLFW_CONTEXT_NO_ERROR) /** - * Specifies whether errors should be generated by the context. - * If enabled, situations that would have generated errors instead - * cause undefined behavior. + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. * * @note Supported since GLFW 3.2. */ diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 1552d9afc..37dfbf47d 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -470,6 +470,10 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf if((glFlags & GLConfiguration::Flag::GpuValidation) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) glFlags |= GLConfiguration::Flag::Debug; + #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2006 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_NO_ERROR, glFlags >= GLConfiguration::Flag::NoError); + #endif + /* Set context version, if user-specified */ if(glConfiguration.version() != GL::Version::None) { Int major, minor; diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 4963f0a7f..34c8a53f5 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -1272,6 +1272,21 @@ class Sdl2Application::GLConfiguration: public GL::Context::Configuration { * @requires_gles Context flags are not available in WebGL. */ ResetIsolation = SDL_GL_CONTEXT_RESET_ISOLATION_FLAG, + + #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2006 || defined(DOXYGEN_GENERATING_OUTPUT) + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * + * @note Available since SDL 2.0.6. + * @requires_gles Context flags are not available in WebGL. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in SDL, thus + handling manually. */ + NoError = 1ull << 32, + #endif #endif /** diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index dbcf71e64..19140d96e 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -67,6 +67,10 @@ typedef void* EGLObjectKHR; typedef void* EGLLabelKHR; typedef void (APIENTRY *EGLDEBUGPROCKHR)(EGLenum error, const char* command, EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel, const char* message); #endif + +#ifndef EGL_KHR_create_context_no_error +#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3 +#endif #endif namespace Magnum { namespace Platform { @@ -310,10 +314,8 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G flags |= Configuration::Flag::Debug; #endif - #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_WEBGL) - const /* Is modified below to work around a SwiftShader limitation */ - #endif - EGLint attributes[] = { + /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ + EGLint attributes[7] = { EGL_CONTEXT_CLIENT_VERSION, #ifdef MAGNUM_TARGET_GLES #if defined(MAGNUM_TARGET_GLES2) || (defined(CORRADE_TARGET_EMSCRIPTEN) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ < 13824) @@ -330,22 +332,31 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G #else 3, #endif - #ifndef MAGNUM_TARGET_WEBGL - /* Needs to be last because we're zeroing this out for SwiftShader (see - below). - Also mask out the upper 32bits used for other flags. */ - EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu), - #endif + /* The rest is added optionally */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_FLAGS_KHR, need to be last */ EGL_NONE }; - #ifdef MAGNUM_TARGET_WEBGL - static_cast(configuration); - static_cast(magnumContext); - #endif + #ifndef MAGNUM_TARGET_WEBGL + std::size_t nextAttribute = 2; + CORRADE_INTERNAL_ASSERT(attributes[nextAttribute] == EGL_NONE); - #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) + if(flags & Configuration::Flag::NoError) { + attributes[nextAttribute++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR; + attributes[nextAttribute++] = true; + } + + /* Context flags need to be last because we're zeroing this out for + SwiftShader (see below). Also mask out the upper 32bits used for other + flags. */ + attributes[nextAttribute++] = EGL_CONTEXT_FLAGS_KHR; + attributes[nextAttribute++] = EGLint(UnsignedLong(flags) & 0xffffffffu); + + CORRADE_INTERNAL_ASSERT(nextAttribute < Containers::arraySize(attributes)); + + #ifdef MAGNUM_TARGET_GLES const Containers::StringView version = eglQueryString(_display, EGL_VERSION); /* SwiftShader 3.3.0.1 blows up on encountering EGL_CONTEXT_FLAGS_KHR with @@ -353,11 +364,17 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G flags, but instead checks for the whole value, so a combination won't work either: https://github.com/google/swiftshader/blob/5fb5e817a20d3e60f29f7338493f922b5ac9d7c4/src/OpenGL/libEGL/libEGL.cpp#L794-L8104 */ if(!(UnsignedLong(flags) & 0xffffffffu) && version.contains("SwiftShader"_s) && (!magnumContext || !magnumContext->isDriverWorkaroundDisabled("swiftshader-no-empty-egl-context-flags"_s))) { - auto& contextFlags = attributes[Containers::arraySize(attributes) - 3]; + auto& contextFlags = attributes[nextAttribute - 2]; CORRADE_INTERNAL_ASSERT(contextFlags == EGL_CONTEXT_FLAGS_KHR); contextFlags = EGL_NONE; } #endif + #endif + + #ifdef MAGNUM_TARGET_WEBGL + static_cast(configuration); + static_cast(magnumContext); + #endif _context = eglCreateContext(_display, config, #ifndef MAGNUM_TARGET_WEBGL @@ -372,15 +389,30 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G if(!_context) { Warning{} << "Platform::WindowlessEglContext: cannot create core context, falling back to compatibility context:" << Implementation::eglErrorString(eglGetError()); - const EGLint fallbackAttributes[] = { + /** @todo duplicated three times, do better */ + EGLint fallbackAttributes[5] = { /* Discard the ForwardCompatible flag for the fallback. Having it set makes the fallback context creation fail on Mesa's Zink (which is just 2.1) and I assume on others as well. Also mask out the upper 32bits used for other flags. */ EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */ EGL_NONE }; + + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(fallbackAttributes[nextFallbackAttribute] == EGL_NONE); + + if(flags & Configuration::Flag::NoError) { + fallbackAttributes[nextFallbackAttribute++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR; + fallbackAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackAttributes)); + _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes); /* Fall back to (forward compatible) GL 2.1 if we are on binary NVidia/AMD @@ -411,16 +443,30 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G { /* Destroy the core context and create a compatibility one */ eglDestroyContext(_display, _context); - const GLint fallbackAttributes[] = { + + /** @todo duplicated three times, do better */ + GLint fallbackAttributes[5] = { /* Discard the ForwardCompatible flag for the fallback. Compared to the above case of a 2.1 fallback it's not really needed here (AFAIK it works in both cases), but let's be - consistent. - - Also mask out the upper 32bits used for other flags. */ + consistent. Also mask out the upper 32bits used for other + flags. */ EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */ EGL_NONE }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(fallbackAttributes[nextFallbackAttribute] == EGL_NONE); + + if(flags & Configuration::Flag::NoError) { + fallbackAttributes[nextFallbackAttribute++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR; + fallbackAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackAttributes)); + _context = eglCreateContext(_display, config, configuration.sharedContext(), fallbackAttributes); } diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index ecbe7c116..afd1e3133 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -208,6 +208,17 @@ class WindowlessEglContext::Configuration: public GL::Context::Configuration { * @requires_gles Context flags are not available in WebGL. */ Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, + + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * @requires_gles Context flags are not available in WebGL. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in EGL, thus + handling manually. */ + NoError = 1ull << 32, #endif /** diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index 71e3e07db..cfeb65a74 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -32,6 +32,10 @@ #include "Magnum/GL/Version.h" +#ifndef GLX_ARB_create_context_no_error +#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3 +#endif + /* Saner way to define the insane Xlib macros (anyway, FUCK YOU XLIB) */ namespace { enum { None = 0, Success = 0 }; } @@ -113,8 +117,9 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; + /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ /* Optimistically choose core context first */ - const GLint contextAttributes[] = { + GLint contextAttributes[11] = { #ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES3 GLX_CONTEXT_MAJOR_VERSION_ARB, 3, @@ -134,9 +139,22 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura /* Mask out the upper 32bits used for other flags */ GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), #endif + + /* The rest is added optionally */ + 0, 0, /* GLX_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextAttribute = 8; + CORRADE_INTERNAL_ASSERT(!contextAttributes[nextAttribute]); + + if(flags & Configuration::Flag::NoError) { + contextAttributes[nextAttribute++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB; + contextAttributes[nextAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextAttribute < Containers::arraySize(contextAttributes)); + { XlibErrorHandler eh{_display}; _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, contextAttributes); @@ -153,15 +171,29 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura w << Debug::nospace << ":" << buffer; } - const GLint fallbackContextAttributes[] = { + /** @todo duplicated three times, do better */ + GLint fallbackContextAttributes[5] = { /* Discard the ForwardCompatible flag for the fallback. Having it set makes the fallback context creation fail on Mesa's Zink (which is just 2.1) and I assume on others as well. Also mask out the upper 32bits used for other flags. */ GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + 0, 0, /* GLX_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(!fallbackContextAttributes[nextFallbackAttribute]); + + if(flags & Configuration::Flag::NoError) { + fallbackContextAttributes[nextFallbackAttribute++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB; + fallbackContextAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackContextAttributes)); + { XlibErrorHandler eh{_display}; _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes); @@ -192,7 +224,9 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura { /* Destroy the core context and create a compatibility one */ glXDestroyContext(_display, _context); - const GLint fallbackContextAttributes[] = { + + /** @todo duplicated three times, do better */ + GLint fallbackContextAttributes[5] = { /* Discard the ForwardCompatible flag for the fallback. Compared to the above case of a 2.1 fallback it's not really needed here (AFAIK it works in both cases), but let's be @@ -200,8 +234,21 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura Also mask out the upper 32bits used for other flags. */ GLX_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + 0, 0, /* GLX_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(!fallbackContextAttributes[nextFallbackAttribute]); + + if(flags & Configuration::Flag::NoError) { + fallbackContextAttributes[nextFallbackAttribute++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB; + fallbackContextAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackContextAttributes)); + { XlibErrorHandler eh{_display}; _context = glXCreateContextAttribsARB(_display, configs[0], configuration.sharedContext(), True, fallbackContextAttributes); diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index 158f19edf..d8fd54874 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -212,6 +212,16 @@ class WindowlessGlxContext::Configuration: public GL::Context::Configuration { */ Debug = GLX_CONTEXT_DEBUG_BIT_ARB, + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in GLX, thus + handling manually. */ + NoError = 1ull << 32, + /** * @copydoc GL::Context::Configuration::Flag::QuietLog * @m_since_latest diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index 13ad08dc5..da9466547 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -40,6 +40,10 @@ #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 #define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 + +#ifndef WGL_ARB_create_context_no_error +#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3 +#endif #endif namespace Magnum { namespace Platform { @@ -126,8 +130,9 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; + /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ /* Optimistically choose core context first */ - const GLint contextAttributes[] = { + GLint contextAttributes[11] = { #ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES3 WGL_CONTEXT_MAJOR_VERSION_ARB, 3, @@ -147,8 +152,22 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G /* Mask out the upper 32bits used for other flags */ WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags) & 0xffffffffu), #endif + + /* The rest is added optionally */ + 0, 0, /* WGL_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + + std::size_t nextAttribute = 8; + CORRADE_INTERNAL_ASSERT(!contextAttributes[nextAttribute]); + + if(flags & Configuration::Flag::NoError) { + contextAttributes[nextAttribute++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB; + contextAttributes[nextAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextAttribute < Containers::arraySize(contextAttributes)); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), contextAttributes); #ifndef MAGNUM_TARGET_GLES @@ -156,12 +175,26 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G if(!_context) { Warning() << "Platform::WindowlessWglContext: cannot create core context, falling back to compatibility context:" << GetLastError(); - const int fallbackContextAttributes[] = { + /** @todo duplicated three times, do better */ + GLint fallbackContextAttributes[5] = { /** @todo or keep the fwcompat? */ /* Mask out the upper 32bits used for other flags */ WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + 0, 0, /* WGL_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(!fallbackContextAttributes[nextFallbackAttribute]); + + if(flags & Configuration::Flag::NoError) { + fallbackContextAttributes[nextFallbackAttribute++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB; + fallbackContextAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackContextAttributes)); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); /* Fall back to (forward compatible) GL 2.1 if we are on binary @@ -190,12 +223,27 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G { /* Destroy the core context and create a compatibility one */ wglDeleteContext(_context); - const int fallbackContextAttributes[] = { + + /** @todo duplicated three times, do better */ + GLint fallbackContextAttributes[5] = { /** @todo or keep the fwcompat? */ /* Mask out the upper 32bits used for other flags */ WGL_CONTEXT_FLAGS_ARB, GLint(UnsignedLong(flags & ~Configuration::Flag::ForwardCompatible) & 0xffffffffu), + + /* The rest is added dynamically */ + 0, 0, /* WGL_CONTEXT_OPENGL_NO_ERROR_ARB */ 0 }; + std::size_t nextFallbackAttribute = 2; + CORRADE_INTERNAL_ASSERT(!fallbackContextAttributes[nextFallbackAttribute]); + + if(flags & Configuration::Flag::NoError) { + fallbackContextAttributes[nextFallbackAttribute++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB; + fallbackContextAttributes[nextFallbackAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextFallbackAttribute < Containers::arraySize(fallbackContextAttributes)); + _context = wglCreateContextAttribsARB(_deviceContext, configuration.sharedContext(), fallbackContextAttributes); } } diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index 067369fcc..d33436358 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -199,6 +199,16 @@ class WindowlessWglContext::Configuration: public GL::Context::Configuration { */ Debug = WGL_CONTEXT_DEBUG_BIT_ARB, + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in WGL, thus + handling manually. */ + NoError = 1ull << 32, + /** * @copydoc GL::Context::Configuration::Flag::QuietLog * @m_since_latest diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 5eac49ebe..182656214 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -32,6 +32,10 @@ #include "Implementation/Egl.h" +#ifndef EGL_KHR_create_context_no_error +#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31B3 +#endif + namespace Magnum { namespace Platform { WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& configuration, GLContext* const magnumContext) { @@ -118,7 +122,8 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; - const EGLint attributes[] = { + /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ + EGLint attributes[7] = { #ifdef MAGNUM_TARGET_GLES EGL_CONTEXT_CLIENT_VERSION, #ifdef MAGNUM_TARGET_GLES3 @@ -131,9 +136,22 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co #endif /* Mask out the upper 32bits used for other flags */ EGL_CONTEXT_FLAGS_KHR, EGLint(UnsignedLong(flags) & 0xffffffffu), + + /* The rest is added optionally */ + EGL_NONE, EGL_NONE, /* EGL_CONTEXT_OPENGL_NO_ERROR_KHR */ EGL_NONE }; + std::size_t nextAttribute = 4; + CORRADE_INTERNAL_ASSERT(attributes[nextAttribute] == EGL_NONE); + + if(flags & Configuration::Flag::NoError) { + attributes[nextAttribute++] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR; + attributes[nextAttribute++] = true; + } + + CORRADE_INTERNAL_ASSERT(nextAttribute < Containers::arraySize(attributes)); + if(!(_context = eglCreateContext(_display, config, configuration.sharedContext(), attributes))) { Error() << "Platform::WindowlessWindowsEglContext: cannot create EGL context:" << Implementation::eglErrorString(eglGetError()); return; diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 7268ad2b8..836b419b1 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -175,6 +175,16 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat */ Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, + /** + * Context without error reporting. Might result in better + * performance, but situations that would have generated errors + * instead cause undefined behavior. + * @m_since_latest + */ + /* Treated as a separate attribute and not a flag in EGL, thus + handling manually. */ + NoError = 1ull << 32, + /** * @copydoc GL::Context::Configuration::Flag::QuietLog * @m_since_latest From 45ccf50b4703e75b11529678b22bb79c5a948ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 1 Mar 2021 19:57:03 +0100 Subject: [PATCH 053/161] GL: implement --magnum-gpu-validation no-error. I wonder if this actually makes any difference on any drivers. --- doc/changelog.dox | 6 +++ src/Magnum/GL/Context.cpp | 8 +++- src/Magnum/GL/Context.h | 44 +++++++++++++------ src/Magnum/Platform/AbstractXApplication.h | 8 +++- src/Magnum/Platform/AndroidApplication.h | 8 +++- src/Magnum/Platform/EmscriptenApplication.h | 8 +++- src/Magnum/Platform/GlfwApplication.cpp | 4 ++ src/Magnum/Platform/GlfwApplication.h | 15 +++++-- src/Magnum/Platform/Sdl2Application.cpp | 4 ++ src/Magnum/Platform/Sdl2Application.h | 15 +++++-- .../Platform/WindowlessCglApplication.h | 8 +++- .../Platform/WindowlessEglApplication.cpp | 2 + .../Platform/WindowlessEglApplication.h | 15 +++++-- .../Platform/WindowlessGlxApplication.cpp | 2 + .../Platform/WindowlessGlxApplication.h | 15 +++++-- .../Platform/WindowlessIosApplication.h | 8 +++- .../Platform/WindowlessWglApplication.cpp | 2 + .../Platform/WindowlessWglApplication.h | 15 +++++-- .../WindowlessWindowsEglApplication.cpp | 2 + .../WindowlessWindowsEglApplication.h | 15 +++++-- 20 files changed, 166 insertions(+), 38 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 1db6285c2..9de2513ae 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -55,6 +55,12 @@ See also: inherited by all @ref Platform::Sdl2Application::GLConfiguration "Platform::*Application::GLConfiguration" and @ref Platform::WindowlessEglApplication::Configuration "Platform::Windowless*Application::Configuration" classes. +- The `--magnum-gpu-validation` option accepts a new value, `no-error`, which + creates OpenGL contexts without error reporting. Those may result in better + performance on certain drivers, however note that errors on such context + have undefined behavior and may cause stability issues. This option is also + programatically settable via a new + @ref GL::Context::Configuration::Flag::GpuValidationNoError flag. - Implemented @gl_extension{EXT,texture_norm16} and @webgl_extension{EXT,texture_norm16} ES and WebGL extensions, making normalized 16-bit texture and renderbuffer formats available on all diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index d1069ac8c..8d04b9a7d 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -693,7 +693,7 @@ Context::Context(NoCreateT, Utility::Arguments& args, Int argc, const char** arg CORRADE_INTERNAL_ASSERT(args.prefix() == "magnum"); args.addOption("disable-workarounds").setHelp("disable-workarounds", "driver workarounds to disable\n (see https://doc.magnum.graphics/magnum/opengl-workarounds.html for detailed info)", "LIST") .addOption("disable-extensions").setHelp("disable-extensions", "API extensions to disable", "LIST") - .addOption("gpu-validation", "off").setHelp("gpu-validation", "GPU validation using KHR_debug (if present)", "off|on") + .addOption("gpu-validation", "off").setHelp("gpu-validation", "GPU validation using KHR_debug (if present)", "off|on|no-error") .addOption("log", "default").setHelp("log", "console logging", "default|quiet|verbose") .setFromEnvironment("disable-workarounds") .setFromEnvironment("disable-extensions") @@ -707,9 +707,11 @@ Context::Context(NoCreateT, Utility::Arguments& args, Int argc, const char** arg else if(args.value("log") == "quiet" || args.value("log") == "QUIET") _configurationFlags |= Configuration::Flag::QuietLog; - /* Decide whether to enable GPU validation */ + /* Decide whether to enable GPU validation / no error context */ if(args.value("gpu-validation") == "on" || args.value("gpu-validation") == "ON") _configurationFlags |= Configuration::Flag::GpuValidation; + else if(args.value("gpu-validation") == "no-error") + _configurationFlags |= Configuration::Flag::GpuValidationNoError; /* If there are any disabled workarounds, save them until tryCreate() uses them. The disableWorkaround() function saves the internal string view @@ -784,6 +786,8 @@ bool Context::tryCreate(const Configuration& configuration) { /* GPU validation is enabled if either enables it */ if(configuration.flags() & Configuration::Flag::GpuValidation) _configurationFlags |= Configuration::Flag::GpuValidation; + if(configuration.flags() & Configuration::Flag::GpuValidationNoError) + _configurationFlags |= Configuration::Flag::GpuValidationNoError; /* Same for windowless */ if(configuration.flags() & Configuration::Flag::Windowless) diff --git a/src/Magnum/GL/Context.h b/src/Magnum/GL/Context.h index 86a6763ed..94d7a4337 100644 --- a/src/Magnum/GL/Context.h +++ b/src/Magnum/GL/Context.h @@ -70,10 +70,11 @@ namespace Implementation { Context before the Configuration class is defined, it has to be here */ enum class ContextConfigurationFlag: UnsignedLong { /* Keeping the 32-bit range reserved for actual GL context flags */ - Windowless = 1ull << 60, - QuietLog = 1ull << 61, - VerboseLog = 1ull << 62, - GpuValidation = 1ull << 63 + Windowless = 1ull << 59, + QuietLog = 1ull << 60, + VerboseLog = 1ull << 61, + GpuValidation = 1ull << 62, + GpuValidationNoError = 1ull << 63 }; typedef Containers::EnumSet ContextConfigurationFlags; CORRADE_ENUMSET_OPERATORS(ContextConfigurationFlags) @@ -165,14 +166,15 @@ Arguments: - `--magnum-disable-extensions LIST` --- API extensions to disable (environment: `MAGNUM_DISABLE_EXTENSIONS`). Corresponds to @ref Configuration::addDisabledExtensions(). -- `--magnum-gpu-validation off|on` --- GPU validation using +- `--magnum-gpu-validation off|on|no-error` --- GPU validation using @gl_extension{KHR,debug}, if present (environment: `MAGNUM_GPU_VALIDATION`) (default: `off`). This sets up @ref DebugOutput callbacks and also causes @ref Platform::Sdl2Application::GLConfiguration::Flag::Debug "GLConfiguration::Flag::Debug" to be enabled for context creation for both windowed and windowless applications on supported platforms. Corresponds to - @ref Configuration::Flag::GpuValidation. + @ref Configuration::Flag::GpuValidation / + @ref Configuration::Flag::GpuValidationNoError. - `--magnum-log default|quiet|verbose` --- console logging (environment: `MAGNUM_LOG`) (default: `default`). Corresponds to @ref Configuration::Flag::QuietLog and @@ -234,9 +236,10 @@ class MAGNUM_GL_EXPORT Context { /** * Debug context. Enabled automatically by @ref Platform windowed * and windowless application implementations if the + * @ref Configuration::Flag::GpuValidation flag is set or if the * `--magnum-gpu-validation` * @ref GL-Context-usage-command-line "command-line option" is - * present. + * set to `on`. * @requires_gl43 Extension @gl_extension{KHR,debug} * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / * @gl_extension{KHR,debug} @@ -258,7 +261,12 @@ class MAGNUM_GL_EXPORT Context { #endif /** - * Context without error reporting + * Context without error reporting. Enabled automatically by + * @ref Platform windowed and windowless application + * implementations if the @ref Configuration::Flag::GpuValidationNoError + * flag is set or if the `--magnum-gpu-validation` + * @ref GL-Context-usage-command-line "command-line option" is + * set to `no-error`. * @requires_gl46 Extension @gl_extension{KHR,no_error} * @requires_es_extension Extension @gl_extension{KHR,no_error} */ @@ -926,7 +934,7 @@ class MAGNUM_GL_EXPORT Context::Configuration { * and, conversely, not possible to enable in any * @ref Platform::Sdl2Application::GLConfiguration::Flag "Platform::*Application::GLConfiguration". */ - Windowless = 1ull << 60, + Windowless = 1ull << 59, /** * Print only warnings and errors instead of the usual startup log @@ -936,7 +944,7 @@ class MAGNUM_GL_EXPORT Context::Configuration { * Corresponds to the `--magnum-log quiet` * @ref GL-Context-usage-command-line "command-line option". */ - QuietLog = 1ull << 61, + QuietLog = 1ull << 60, /** * Print additional information on startup in addition to the usual @@ -946,15 +954,25 @@ class MAGNUM_GL_EXPORT Context::Configuration { * Corresponds to the `--magnum-log verbose` * @ref GL-Context-usage-command-line "command-line option". */ - VerboseLog = 1ull << 62, + VerboseLog = 1ull << 61, /** - * Enable GPU validation, if available. + * Enable GPU validation, if available. Has a precedence over + * @ref Flag::GpuValidationNoError. * * Corresponds to the `--magnum-gou-validation on` * @ref GL-Context-usage-command-line "command-line option". */ - GpuValidation = 1ull << 63 + GpuValidation = 1ull << 62, + + /** + * Enable a context without error reporting, if available. Ignored + * if @ref Flag::GpuValidation is set. + * + * Corresponds to the `--magnum-gou-validation no-error` + * @ref GL-Context-usage-command-line "command-line option". + */ + GpuValidationNoError = 1ull << 63 }; #else typedef Implementation::ContextConfigurationFlag Flag; diff --git a/src/Magnum/Platform/AbstractXApplication.h b/src/Magnum/Platform/AbstractXApplication.h index 3b02f92f7..0291e3cc2 100644 --- a/src/Magnum/Platform/AbstractXApplication.h +++ b/src/Magnum/Platform/AbstractXApplication.h @@ -365,7 +365,13 @@ class AbstractXApplication::GLConfiguration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/AndroidApplication.h b/src/Magnum/Platform/AndroidApplication.h index 11ea3d620..7790a0662 100644 --- a/src/Magnum/Platform/AndroidApplication.h +++ b/src/Magnum/Platform/AndroidApplication.h @@ -478,7 +478,13 @@ class AndroidApplication::GLConfiguration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/EmscriptenApplication.h b/src/Magnum/Platform/EmscriptenApplication.h index fd76e5867..949355f56 100644 --- a/src/Magnum/Platform/EmscriptenApplication.h +++ b/src/Magnum/Platform/EmscriptenApplication.h @@ -1019,7 +1019,13 @@ class EmscriptenApplication::GLConfiguration: public GL::Context::Configuration * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/GlfwApplication.cpp b/src/Magnum/Platform/GlfwApplication.cpp index 1527651d2..70da60d79 100644 --- a/src/Magnum/Platform/GlfwApplication.cpp +++ b/src/Magnum/Platform/GlfwApplication.cpp @@ -433,6 +433,10 @@ bool GlfwApplication::tryCreate(const Configuration& configuration, const GLConf GLConfiguration::Flags glFlags = glConfiguration.flags(); if((glFlags & GLConfiguration::Flag::GpuValidation) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) glFlags |= GLConfiguration::Flag::Debug; + #ifdef GLFW_CONTEXT_NO_ERROR + else if((glFlags & GLConfiguration::Flag::GpuValidationNoError) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidationNoError)) + glFlags |= GLConfiguration::Flag::NoError; + #endif #ifdef GLFW_CONTEXT_NO_ERROR glfwWindowHint(GLFW_CONTEXT_NO_ERROR, glFlags >= GLConfiguration::Flag::NoError); diff --git a/src/Magnum/Platform/GlfwApplication.h b/src/Magnum/Platform/GlfwApplication.h index 327511c4c..c8f45615b 100644 --- a/src/Magnum/Platform/GlfwApplication.h +++ b/src/Magnum/Platform/GlfwApplication.h @@ -804,7 +804,10 @@ class GlfwApplication::GLConfiguration: public GL::Context::Configuration { /** * Context without error reporting. Might result in better * performance, but situations that would have generated errors - * instead cause undefined behavior. + * instead cause undefined behavior. Enabled automatically if + * supported by the driver and the @ref Flag::GpuValidationNoError + * flag is set or if the `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" + * is set to `no-error`. * * @note Supported since GLFW 3.2. */ @@ -815,7 +818,7 @@ class GlfwApplication::GLConfiguration: public GL::Context::Configuration { * Debug context. Enabled automatically if supported by the driver * and the @ref Flag::GpuValidation flag is set or if the * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" - * is present. + * is set to `on`. */ Debug = 1 << 2, @@ -837,7 +840,13 @@ class GlfwApplication::GLConfiguration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/Sdl2Application.cpp b/src/Magnum/Platform/Sdl2Application.cpp index 37dfbf47d..8a536e9e7 100644 --- a/src/Magnum/Platform/Sdl2Application.cpp +++ b/src/Magnum/Platform/Sdl2Application.cpp @@ -469,6 +469,10 @@ bool Sdl2Application::tryCreate(const Configuration& configuration, const GLConf GLConfiguration::Flags glFlags = glConfiguration.flags(); if((glFlags & GLConfiguration::Flag::GpuValidation) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) glFlags |= GLConfiguration::Flag::Debug; + #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2006 + else if((glFlags & GLConfiguration::Flag::GpuValidationNoError) || (_context->configurationFlags() & GL::Context::Configuration::Flag::GpuValidationNoError)) + glFlags |= GLConfiguration::Flag::NoError; + #endif #if SDL_MAJOR_VERSION*1000 + SDL_MINOR_VERSION*100 + SDL_PATCHLEVEL >= 2006 SDL_GL_SetAttribute(SDL_GL_CONTEXT_NO_ERROR, glFlags >= GLConfiguration::Flag::NoError); diff --git a/src/Magnum/Platform/Sdl2Application.h b/src/Magnum/Platform/Sdl2Application.h index 34c8a53f5..23b0dd86d 100644 --- a/src/Magnum/Platform/Sdl2Application.h +++ b/src/Magnum/Platform/Sdl2Application.h @@ -1256,7 +1256,7 @@ class Sdl2Application::GLConfiguration: public GL::Context::Configuration { * Debug context. Enabled automatically if supported by the driver * and the @ref Flag::GpuValidation flag is set or if the * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" - * is present. + * is set to `on`. * @requires_gles Context flags are not available in WebGL. */ Debug = SDL_GL_CONTEXT_DEBUG_FLAG, @@ -1277,7 +1277,10 @@ class Sdl2Application::GLConfiguration: public GL::Context::Configuration { /** * Context without error reporting. Might result in better * performance, but situations that would have generated errors - * instead cause undefined behavior. + * instead cause undefined behavior. Enabled automatically if + * supported by the driver and the @ref Flag::GpuValidationNoError + * flag is set or if the `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" + * is set to `no-error`. * * @note Available since SDL 2.0.6. * @requires_gles Context flags are not available in WebGL. @@ -1305,7 +1308,13 @@ class Sdl2Application::GLConfiguration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/WindowlessCglApplication.h b/src/Magnum/Platform/WindowlessCglApplication.h index ecb3dc915..0d76c5841 100644 --- a/src/Magnum/Platform/WindowlessCglApplication.h +++ b/src/Magnum/Platform/WindowlessCglApplication.h @@ -188,7 +188,13 @@ class WindowlessCglContext::Configuration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/WindowlessEglApplication.cpp b/src/Magnum/Platform/WindowlessEglApplication.cpp index 19140d96e..89fa13406 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessEglApplication.cpp @@ -312,6 +312,8 @@ WindowlessEglContext::WindowlessEglContext(const Configuration& configuration, G Configuration::Flags flags = configuration.flags(); if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; + else if((flags & Configuration::Flag::GpuValidationNoError) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidationNoError)) + flags |= Configuration::Flag::NoError; #endif /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index afd1e3133..7aa6d7888 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -204,7 +204,7 @@ class WindowlessEglContext::Configuration: public GL::Context::Configuration { * Debug context. Enabled automatically if supported by the driver * and the @ref Flag::GpuValidation flag is set or if the * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" - * is present. + * is set to `on`. * @requires_gles Context flags are not available in WebGL. */ Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, @@ -212,7 +212,10 @@ class WindowlessEglContext::Configuration: public GL::Context::Configuration { /** * Context without error reporting. Might result in better * performance, but situations that would have generated errors - * instead cause undefined behavior. + * instead cause undefined behavior. Enabled automatically if + * supported by the driver and the @ref Flag::GpuValidationNoError + * flag is set or if the `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" + * is set to `no-error`. * @requires_gles Context flags are not available in WebGL. * @m_since_latest */ @@ -237,7 +240,13 @@ class WindowlessEglContext::Configuration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/WindowlessGlxApplication.cpp b/src/Magnum/Platform/WindowlessGlxApplication.cpp index cfeb65a74..ed0d2d80e 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.cpp +++ b/src/Magnum/Platform/WindowlessGlxApplication.cpp @@ -116,6 +116,8 @@ WindowlessGlxContext::WindowlessGlxContext(const WindowlessGlxContext::Configura Configuration::Flags flags = configuration.flags(); if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; + else if((flags & Configuration::Flag::GpuValidationNoError) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidationNoError)) + flags |= Configuration::Flag::NoError; /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ /* Optimistically choose core context first */ diff --git a/src/Magnum/Platform/WindowlessGlxApplication.h b/src/Magnum/Platform/WindowlessGlxApplication.h index d8fd54874..f549f7d1f 100644 --- a/src/Magnum/Platform/WindowlessGlxApplication.h +++ b/src/Magnum/Platform/WindowlessGlxApplication.h @@ -208,14 +208,17 @@ class WindowlessGlxContext::Configuration: public GL::Context::Configuration { * Debug context. Enabled automatically if supported by the driver * and the @ref Flag::GpuValidation flag is set or if the * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" - * is present. + * is set to `on`. */ Debug = GLX_CONTEXT_DEBUG_BIT_ARB, /** * Context without error reporting. Might result in better * performance, but situations that would have generated errors - * instead cause undefined behavior. + * instead cause undefined behavior. Enabled automatically if + * supported by the driver and the @ref Flag::GpuValidationNoError + * flag is set or if the `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" + * is set to `no-error`. * @m_since_latest */ /* Treated as a separate attribute and not a flag in GLX, thus @@ -238,7 +241,13 @@ class WindowlessGlxContext::Configuration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/WindowlessIosApplication.h b/src/Magnum/Platform/WindowlessIosApplication.h index 5b55b2643..5932a13b4 100644 --- a/src/Magnum/Platform/WindowlessIosApplication.h +++ b/src/Magnum/Platform/WindowlessIosApplication.h @@ -179,7 +179,13 @@ class WindowlessIosContext::Configuration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/WindowlessWglApplication.cpp b/src/Magnum/Platform/WindowlessWglApplication.cpp index da9466547..760c1dcd6 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWglApplication.cpp @@ -129,6 +129,8 @@ WindowlessWglContext::WindowlessWglContext(const Configuration& configuration, G Configuration::Flags flags = configuration.flags(); if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; + else if((flags & Configuration::Flag::GpuValidationNoError) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidationNoError)) + flags |= Configuration::Flag::NoError; /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ /* Optimistically choose core context first */ diff --git a/src/Magnum/Platform/WindowlessWglApplication.h b/src/Magnum/Platform/WindowlessWglApplication.h index d33436358..923b51514 100644 --- a/src/Magnum/Platform/WindowlessWglApplication.h +++ b/src/Magnum/Platform/WindowlessWglApplication.h @@ -195,14 +195,17 @@ class WindowlessWglContext::Configuration: public GL::Context::Configuration { * Debug context. Enabled automatically if supported by the driver * and the @ref Flag::GpuValidation flag is set or if the * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" - * is present. + * is set to `on`. */ Debug = WGL_CONTEXT_DEBUG_BIT_ARB, /** * Context without error reporting. Might result in better * performance, but situations that would have generated errors - * instead cause undefined behavior. + * instead cause undefined behavior. Enabled automatically if + * supported by the driver and the @ref Flag::GpuValidationNoError + * flag is set or if the `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" + * is set to `no-error`. * @m_since_latest */ /* Treated as a separate attribute and not a flag in WGL, thus @@ -225,7 +228,13 @@ class WindowlessWglContext::Configuration: public GL::Context::Configuration { * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp index 182656214..c959bdbfc 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.cpp @@ -121,6 +121,8 @@ WindowlessWindowsEglContext::WindowlessWindowsEglContext(const Configuration& co Configuration::Flags flags = configuration.flags(); if((flags & Configuration::Flag::GpuValidation) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidation)) flags |= Configuration::Flag::Debug; + else if((flags & Configuration::Flag::GpuValidationNoError) || (magnumContext && magnumContext->configurationFlags() & GL::Context::Configuration::Flag::GpuValidationNoError)) + flags |= Configuration::Flag::NoError; /** @todo needs a growable DynamicArray with disabled alloc or somesuch */ EGLint attributes[7] = { diff --git a/src/Magnum/Platform/WindowlessWindowsEglApplication.h b/src/Magnum/Platform/WindowlessWindowsEglApplication.h index 836b419b1..e0a6df5f8 100644 --- a/src/Magnum/Platform/WindowlessWindowsEglApplication.h +++ b/src/Magnum/Platform/WindowlessWindowsEglApplication.h @@ -171,14 +171,17 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat * Debug context. Enabled automatically if supported by the driver * and the @ref Flag::GpuValidation flag is set or if the * `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" - * is present. + * is set to `on`. */ Debug = EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR, /** * Context without error reporting. Might result in better * performance, but situations that would have generated errors - * instead cause undefined behavior. + * instead cause undefined behavior. Enabled automatically if + * supported by the driver and the @ref Flag::GpuValidationNoError + * flag is set or if the `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" + * is set to `no-error`. * @m_since_latest */ /* Treated as a separate attribute and not a flag in EGL, thus @@ -201,7 +204,13 @@ class WindowlessWindowsEglContext::Configuration: public GL::Context::Configurat * @copydoc GL::Context::Configuration::Flag::GpuValidation * @m_since_latest */ - GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation) + GpuValidation = UnsignedLong(GL::Context::Configuration::Flag::GpuValidation), + + /** + * @copydoc GL::Context::Configuration::Flag::GpuValidationNoError + * @m_since_latest + */ + GpuValidationNoError = UnsignedLong(GL::Context::Configuration::Flag::GpuValidationNoError) }; /** From 8c6efa5b7825dc834ef28551153d016789fd8a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 2 Mar 2021 15:50:06 +0100 Subject: [PATCH 054/161] GL: remove one function pointer indirection in DSA setUniform() calls. Instead of wrapping glProgramUniform*() inside a member function, we now call that function directly, which allows us to remove 2/3rds of AbstractShaderProgram members. The non-DSA code path is still implemented though member functions, though they are now static, mimic the signature of the DSA APIs and do a use() + glUniform*() internally. --- src/Magnum/GL/AbstractShaderProgram.cpp | 574 +++++------------- src/Magnum/GL/AbstractShaderProgram.h | 163 ++--- .../GL/Implementation/ShaderProgramState.cpp | 178 +++--- .../GL/Implementation/ShaderProgramState.h | 68 +-- 4 files changed, 299 insertions(+), 684 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index 44ab50947..752c0b58b 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -427,12 +427,14 @@ void AbstractShaderProgram::dispatchCompute(const Vector3ui& workgroupCount) { } #endif -void AbstractShaderProgram::use() { +void AbstractShaderProgram::use(const GLuint id) { /* Use only if the program isn't already in use */ GLuint& current = Context::current().state().shaderProgram.current; - if(current != _id) glUseProgram(current = _id); + if(current != id) glUseProgram(current = id); } +void AbstractShaderProgram::use() { use(_id); } + void AbstractShaderProgram::attachShader(Shader& shader) { glAttachShader(_id, shader.id()); } @@ -563,620 +565,316 @@ UnsignedInt AbstractShaderProgram::uniformBlockIndexInternal(const Containers::A #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - (this->*Context::current().state().shaderProgram.uniform1fvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform1fvImplementation(_id, location, values.size(), values.data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLfloat* const values) { - use(); +void AbstractShaderProgram::uniform1fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLfloat* const values) { + use(id); glUniform1fv(location, count, values); } -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLfloat* const values) { - glProgramUniform1fv(_id, location, count, values); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const GLfloat* const values) { - glProgramUniform1fvEXT(_id, location, count, values); -} -#endif - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform2fvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform2fvImplementation(_id, location, values.size(), values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) { - use(); - glUniform2fv(location, count, values[0].data()); +void AbstractShaderProgram::uniform2fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLfloat* const values) { + use(id); + glUniform2fv(location, count, values); } -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) { - glProgramUniform2fv(_id, location, count, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<2, GLfloat>* const values) { - glProgramUniform2fvEXT(_id, location, count, values[0].data()); -} -#endif - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform3fvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) { - use(); - glUniform3fv(location, count, values[0].data()); + Context::current().state().shaderProgram.uniform3fvImplementation(_id, location, values.size(), values.data()->data()); } -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) { - glProgramUniform3fv(_id, location, count, values[0].data()); +void AbstractShaderProgram::uniform3fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLfloat* const values) { + use(id); + glUniform3fv(location, count, values); } -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<3, GLfloat>* const values) { - glProgramUniform3fvEXT(_id, location, count, values[0].data()); -} -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform4fvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) { - use(); - glUniform4fv(location, count, values[0].data()); -} - -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) { - glProgramUniform4fv(_id, location, count, values[0].data()); + Context::current().state().shaderProgram.uniform4fvImplementation(_id, location, values.size(), values.data()->data()); } -#endif -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<4, GLfloat>* const values) { - glProgramUniform4fvEXT(_id, location, count, values[0].data()); +void AbstractShaderProgram::uniform4fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLfloat* const values) { + use(id); + glUniform4fv(location, count, values); } -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - (this->*Context::current().state().shaderProgram.uniform1ivImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform1ivImplementation(_id, location, values.size(), values.data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLint* values) { - use(); +void AbstractShaderProgram::uniform1ivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLint* values) { + use(id); glUniform1iv(location, count, values); } -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLint* const values) { - glProgramUniform1iv(_id, location, count, values); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const GLint* const values) { - glProgramUniform1ivEXT(_id, location, count, values); -} -#endif - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform2ivImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) { - use(); - glUniform2iv(location, count, values[0].data()); -} - -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) { - glProgramUniform2iv(_id, location, count, values[0].data()); + Context::current().state().shaderProgram.uniform2ivImplementation(_id, location, values.size(), values.data()->data()); } -#endif -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<2, GLint>* const values) { - glProgramUniform2ivEXT(_id, location, count, values[0].data()); +void AbstractShaderProgram::uniform2ivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLint* const values) { + use(id); + glUniform2iv(location, count, values); } -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform3ivImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform3ivImplementation(_id, location, values.size(), values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) { - use(); - glUniform3iv(location, count, values[0].data()); +void AbstractShaderProgram::uniform3ivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLint* const values) { + use(id); + glUniform3iv(location, count, values); } -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) { - glProgramUniform3iv(_id, location, count, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<3, GLint>* const values) { - glProgramUniform3ivEXT(_id, location, count, values[0].data()); -} -#endif - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform4ivImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform4ivImplementation(_id, location, values.size(), values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) { - use(); - glUniform4iv(location, count, values[0].data()); +void AbstractShaderProgram::uniform4ivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLint* const values) { + use(id); + glUniform4iv(location, count, values); } -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) { - glProgramUniform4iv(_id, location, count, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<4, GLint>* const values) { - glProgramUniform4ivEXT(_id, location, count, values[0].data()); -} -#endif - #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - (this->*Context::current().state().shaderProgram.uniform1uivImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform1uivImplementation(_id, location, values.size(), values.data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLuint* const values) { - use(); +void AbstractShaderProgram::uniform1uivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLuint* const values) { + use(id); glUniform1uiv(location, count, values); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLuint* const values) { - glProgramUniform1uiv(_id, location, count, values); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const GLuint* const values) { - glProgramUniform1uivEXT(_id, location, count, values); -} -#endif - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform2uivImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform2uivImplementation(_id, location, values.size(), values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) { - use(); - glUniform2uiv(location, count, values[0].data()); +void AbstractShaderProgram::uniform2uivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLuint* const values) { + use(id); + glUniform2uiv(location, count, values); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) { - glProgramUniform2uiv(_id, location, count, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<2, GLuint>* const values) { - glProgramUniform2uivEXT(_id, location, count, values[0].data()); -} -#endif - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform3uivImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) { - use(); - glUniform3uiv(location, count, values[0].data()); + Context::current().state().shaderProgram.uniform3uivImplementation(_id, location, values.size(), values.data()->data()); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) { - glProgramUniform3uiv(_id, location, count, values[0].data()); +void AbstractShaderProgram::uniform3uivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLuint* const values) { + use(id); + glUniform3uiv(location, count, values); } -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<3, GLuint>* const values) { - glProgramUniform3uivEXT(_id, location, count, values[0].data()); -} -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform4uivImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) { - use(); - glUniform4uiv(location, count, values[0].data()); + Context::current().state().shaderProgram.uniform4uivImplementation(_id, location, values.size(), values.data()->data()); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) { - glProgramUniform4uiv(_id, location, count, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::Vector<4, GLuint>* const values) { - glProgramUniform4uivEXT(_id, location, count, values[0].data()); +void AbstractShaderProgram::uniform4uivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLuint* const values) { + use(id); + glUniform4uiv(location, count, values); } #endif -#endif #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - (this->*Context::current().state().shaderProgram.uniform1dvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform1dvImplementation(_id, location, values.size(), values.data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const GLdouble* const values) { - use(); +void AbstractShaderProgram::uniform1dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLdouble* const values) { + use(id); glUniform1dv(location, count, values); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const GLdouble* const values) { - glProgramUniform1dv(_id, location, count, values); -} - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform2dvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) { - use(); - glUniform2dv(location, count, values[0].data()); + Context::current().state().shaderProgram.uniform2dvImplementation(_id, location, values.size(), values.data()->data()); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<2, GLdouble>* const values) { - glProgramUniform2dv(_id, location, count, values[0].data()); +void AbstractShaderProgram::uniform2dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLdouble* const values) { + use(id); + glUniform2dv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform3dvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniform3dvImplementation(_id, location, values.size(), values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) { - use(); - glUniform3dv(location, count, values[0].data()); -} - -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<3, GLdouble>* const values) { - glProgramUniform3dv(_id, location, count, values[0].data()); +void AbstractShaderProgram::uniform3dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLdouble* const values) { + use(id); + glUniform3dv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniform4dvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) { - use(); - glUniform4dv(location, count, values[0].data()); + Context::current().state().shaderProgram.uniform4dvImplementation(_id, location, values.size(), values.data()->data()); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::Vector<4, GLdouble>* const values) { - glProgramUniform4dv(_id, location, count, values[0].data()); +void AbstractShaderProgram::uniform4dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLdouble* const values) { + use(id); + glUniform4dv(location, count, values); } #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix2fvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniformMatrix2fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) { - use(); - glUniformMatrix2fv(location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix2fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix2fv(location, count, transpose, values); } -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) { - glProgramUniformMatrix2fv(_id, location, count, GL_FALSE, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* const values) { - glProgramUniformMatrix2fvEXT(_id, location, count, GL_FALSE, values[0].data()); -} -#endif - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix3fvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniformMatrix3fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) { - use(); - glUniformMatrix3fv(location, count, GL_FALSE, values[0].data()); -} - -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) { - glProgramUniformMatrix3fv(_id, location, count, GL_FALSE, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* const values) { - glProgramUniformMatrix3fvEXT(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix3fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix3fv(location, count, transpose, values); } -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix4fvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniformMatrix4fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) { - use(); - glUniformMatrix4fv(location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix4fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix4fv(location, count, transpose, values); } -#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) { - glProgramUniformMatrix4fv(_id, location, count, GL_FALSE, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* const values) { - glProgramUniformMatrix4fvEXT(_id, location, count, GL_FALSE, values[0].data()); -} -#endif - #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix2x3fvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) { - use(); - glUniformMatrix2x3fv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix2x3fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) { - glProgramUniformMatrix2x3fv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix2x3fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix2x3fv(location, count, transpose, values); } -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* const values) { - glProgramUniformMatrix2x3fvEXT(_id, location, count, GL_FALSE, values[0].data()); -} -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix3x2fvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) { - use(); - glUniformMatrix3x2fv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix3x2fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) { - glProgramUniformMatrix3x2fv(_id, location, count, GL_FALSE, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* const values) { - glProgramUniformMatrix3x2fvEXT(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix3x2fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix3x2fv(location, count, transpose, values); } -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix2x4fvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) { - use(); - glUniformMatrix2x4fv(location, count, GL_FALSE, values[0].data()); -} - -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) { - glProgramUniformMatrix2x4fv(_id, location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix2x4fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -#endif -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* const values) { - glProgramUniformMatrix2x4fvEXT(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix2x4fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix2x4fv(location, count, transpose, values); } -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix4x2fvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) { - use(); - glUniformMatrix4x2fv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix4x2fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) { - glProgramUniformMatrix4x2fv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix4x2fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix4x2fv(location, count, transpose, values); } -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* const values) { - glProgramUniformMatrix4x2fvEXT(_id, location, count, GL_FALSE, values[0].data()); -} -#endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix3x4fvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniformMatrix3x4fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) { - use(); - glUniformMatrix3x4fv(location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix3x4fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix3x4fv(location, count, transpose, values); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) { - glProgramUniformMatrix3x4fv(_id, location, count, GL_FALSE, values[0].data()); -} -#endif - -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* const values) { - glProgramUniformMatrix3x4fvEXT(_id, location, count, GL_FALSE, values[0].data()); -} -#endif - void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix4x3fvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) { - use(); - glUniformMatrix4x3fv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix4x3fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -#ifndef MAGNUM_TARGET_WEBGL -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) { - glProgramUniformMatrix4x3fv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix4x3fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { + use(id); + glUniformMatrix4x3fv(location, count, transpose, values); } #endif -#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) -void AbstractShaderProgram::uniformImplementationSSOEXT(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* const values) { - glProgramUniformMatrix4x3fvEXT(_id, location, count, GL_FALSE, values[0].data()); -} -#endif -#endif - #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix2dvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) { - use(); - glUniformMatrix2dv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix2dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* const values) { - glProgramUniformMatrix2dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix2dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix2dv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix3dvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) { - use(); - glUniformMatrix3dv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix3dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* const values) { - glProgramUniformMatrix3dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix3dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix3dv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix4dvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniformMatrix4dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) { - use(); - glUniformMatrix4dv(location, count, GL_FALSE, values[0].data()); -} - -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* const values) { - glProgramUniformMatrix4dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix4dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix4dv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix2x3dvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniformMatrix2x3dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) { - use(); - glUniformMatrix2x3dv(location, count, GL_FALSE, values[0].data()); -} - -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* const values) { - glProgramUniformMatrix2x3dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix2x3dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix2x3dv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix3x2dvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) { - use(); - glUniformMatrix3x2dv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix3x2dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* const values) { - glProgramUniformMatrix3x2dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix3x2dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix3x2dv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix2x4dvImplementation)(location, values.size(), values); + Context::current().state().shaderProgram.uniformMatrix2x4dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) { - use(); - glUniformMatrix2x4dv(location, count, GL_FALSE, values[0].data()); -} - -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* const values) { - glProgramUniformMatrix2x4dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix2x4dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix2x4dv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix4x2dvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) { - use(); - glUniformMatrix4x2dv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix4x2dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* const values) { - glProgramUniformMatrix4x2dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix4x2dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix4x2dv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix3x4dvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) { - use(); - glUniformMatrix3x4dv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix3x4dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* const values) { - glProgramUniformMatrix3x4dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix3x4dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix3x4dv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - (this->*Context::current().state().shaderProgram.uniformMatrix4x3dvImplementation)(location, values.size(), values); -} - -void AbstractShaderProgram::uniformImplementationDefault(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) { - use(); - glUniformMatrix4x3dv(location, count, GL_FALSE, values[0].data()); + Context::current().state().shaderProgram.uniformMatrix4x3dvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); } -void AbstractShaderProgram::uniformImplementationSSO(const GLint location, const GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* const values) { - glProgramUniformMatrix4x3dv(_id, location, count, GL_FALSE, values[0].data()); +void AbstractShaderProgram::uniformMatrix4x3dvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLdouble* const values) { + use(id); + glUniformMatrix4x3dv(location, count, transpose, values); } #endif diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index 07cb01f77..9f17ffdf7 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -1361,139 +1361,56 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { static MAGNUM_GL_LOCAL void cleanLogImplementationAngle(std::string& message); #endif + MAGNUM_GL_LOCAL static void use(GLuint id); void use(); - /* - Currently, there are three supported ways to call glProgramUniform(): - - - EXT_separate_shader_objects (OpenGL ES extension, EXT suffix) - - ARB_separate_shader_objects (desktop GL only, no suffix) - - OpenGL ES 3.1, no suffix - - To avoid copypasta and filesize bloat, this is merged to just two - variants of implementation functions: - - - uniformImplementationSSO() -- functions without suffix, used if - ARB_separate_shader_objects desktop extension or OpenGL ES 3.1 - is available, completely disabled for ES2 - - uniformImplementationSSOEXT() -- functions with EXT suffix, used - if EXT_separate_shader_objects ES 2.0 / ES 3.0 extension is - available - */ - - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLfloat* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLint* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLint>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLint>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLint>* values); + /* To avoid pointless extra function pointer indirections and copypaste + for all suffixed/unsuffixed variants, these are all static with a + signature matching the DSA APIs. On DSA-enabled platforms the + glProgramUniform*() functions are used directly, otherwise these all + use() the shader first and then call the old-style API. */ + MAGNUM_GL_LOCAL static void uniform1fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniform2fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniform3fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniform4fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniform1ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); + MAGNUM_GL_LOCAL static void uniform2ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); + MAGNUM_GL_LOCAL static void uniform3ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); + MAGNUM_GL_LOCAL static void uniform4ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); #ifndef MAGNUM_TARGET_GLES2 - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLuint* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values); + MAGNUM_GL_LOCAL static void uniform1uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); + MAGNUM_GL_LOCAL static void uniform2uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); + MAGNUM_GL_LOCAL static void uniform3uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); + MAGNUM_GL_LOCAL static void uniform4uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); #endif #ifndef MAGNUM_TARGET_GLES - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const GLdouble* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values); - #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLfloat* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLint* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLuint* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values); - #endif - #ifndef MAGNUM_TARGET_GLES - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const GLdouble* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<2, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<3, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::Vector<4, GLdouble>* values); - #endif - #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const GLfloat* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const GLint* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLint>* values); - #ifndef MAGNUM_TARGET_GLES2 - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const GLuint* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<2, GLuint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<3, GLuint>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::Vector<4, GLuint>* values); - #endif + MAGNUM_GL_LOCAL static void uniform1dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniform2dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniform3dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniform4dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); #endif - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values); + MAGNUM_GL_LOCAL static void uniformMatrix2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniformMatrix3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniformMatrix4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); #ifndef MAGNUM_TARGET_GLES2 - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values); + MAGNUM_GL_LOCAL static void uniformMatrix2x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniformMatrix3x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniformMatrix2x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniformMatrix4x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniformMatrix3x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void uniformMatrix4x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); #endif #ifndef MAGNUM_TARGET_GLES - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationDefault(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values); - #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values); - #endif - #ifndef MAGNUM_TARGET_GLES - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLdouble>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSO(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLdouble>* values); - #endif - #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 4, GLfloat>* values); - #ifndef MAGNUM_TARGET_GLES2 - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 3, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<2, 4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 2, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<3, 4, GLfloat>* values); - void MAGNUM_GL_LOCAL uniformImplementationSSOEXT(GLint location, GLsizei count, const Math::RectangularMatrix<4, 3, GLfloat>* values); - #endif + MAGNUM_GL_LOCAL static void uniformMatrix2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniformMatrix3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniformMatrix4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniformMatrix2x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniformMatrix3x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniformMatrix2x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniformMatrix4x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniformMatrix3x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void uniformMatrix4x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); #endif GLuint _id; diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.cpp b/src/Magnum/GL/Implementation/ShaderProgramState.cpp index 141197fce..74ab8d6f0 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/GL/Implementation/ShaderProgramState.cpp @@ -90,44 +90,44 @@ ShaderProgramState::ShaderProgramState(Context& context, Containers::StaticArray Extensions::ARB::separate_shader_objects::string(); #endif - uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform1fvImplementation = glProgramUniform1fv; + uniform2fvImplementation = glProgramUniform2fv; + uniform3fvImplementation = glProgramUniform3fv; + uniform4fvImplementation = glProgramUniform4fv; + uniform1ivImplementation = glProgramUniform1iv; + uniform2ivImplementation = glProgramUniform2iv; + uniform3ivImplementation = glProgramUniform3iv; + uniform4ivImplementation = glProgramUniform4iv; + uniform1uivImplementation = glProgramUniform1uiv; + uniform2uivImplementation = glProgramUniform2uiv; + uniform3uivImplementation = glProgramUniform3uiv; + uniform4uivImplementation = glProgramUniform4uiv; #ifndef MAGNUM_TARGET_GLES - uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniform1dvImplementation = glProgramUniform1dv; + uniform2dvImplementation = glProgramUniform2dv; + uniform3dvImplementation = glProgramUniform3dv; + uniform4dvImplementation = glProgramUniform4dv; #endif - uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix2fvImplementation = glProgramUniformMatrix2fv; + uniformMatrix3fvImplementation = glProgramUniformMatrix3fv; + uniformMatrix4fvImplementation = glProgramUniformMatrix4fv; + uniformMatrix2x3fvImplementation = glProgramUniformMatrix2x3fv; + uniformMatrix3x2fvImplementation = glProgramUniformMatrix3x2fv; + uniformMatrix2x4fvImplementation = glProgramUniformMatrix2x4fv; + uniformMatrix4x2fvImplementation = glProgramUniformMatrix4x2fv; + uniformMatrix3x4fvImplementation = glProgramUniformMatrix3x4fv; + uniformMatrix4x3fvImplementation = glProgramUniformMatrix4x3fv; #ifndef MAGNUM_TARGET_GLES - uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; - uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationSSO; + uniformMatrix2dvImplementation = glProgramUniformMatrix2dv; + uniformMatrix3dvImplementation = glProgramUniformMatrix3dv; + uniformMatrix4dvImplementation = glProgramUniformMatrix4dv; + uniformMatrix2x3dvImplementation = glProgramUniformMatrix2x3dv; + uniformMatrix3x2dvImplementation = glProgramUniformMatrix3x2dv; + uniformMatrix2x4dvImplementation = glProgramUniformMatrix2x4dv; + uniformMatrix4x2dvImplementation = glProgramUniformMatrix4x2dv; + uniformMatrix3x4dvImplementation = glProgramUniformMatrix3x4dv; + uniformMatrix4x3dvImplementation = glProgramUniformMatrix4x3dv; #endif } else #endif @@ -137,77 +137,77 @@ ShaderProgramState::ShaderProgramState(Context& context, Containers::StaticArray extensions[Extensions::EXT::separate_shader_objects::Index] = Extensions::EXT::separate_shader_objects::string(); - uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; + uniform1fvImplementation = glProgramUniform1fvEXT; + uniform2fvImplementation = glProgramUniform2fvEXT; + uniform3fvImplementation = glProgramUniform3fvEXT; + uniform4fvImplementation = glProgramUniform4fvEXT; + uniform1ivImplementation = glProgramUniform1ivEXT; + uniform2ivImplementation = glProgramUniform2ivEXT; + uniform3ivImplementation = glProgramUniform3ivEXT; + uniform4ivImplementation = glProgramUniform4ivEXT; #ifndef MAGNUM_TARGET_GLES2 - uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; + uniform1uivImplementation = glProgramUniform1uivEXT; + uniform2uivImplementation = glProgramUniform2uivEXT; + uniform3uivImplementation = glProgramUniform3uivEXT; + uniform4uivImplementation = glProgramUniform4uivEXT; #endif - uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; + uniformMatrix2fvImplementation = glProgramUniformMatrix2fvEXT; + uniformMatrix3fvImplementation = glProgramUniformMatrix3fvEXT; + uniformMatrix4fvImplementation = glProgramUniformMatrix4fvEXT; #ifndef MAGNUM_TARGET_GLES2 - uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; - uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationSSOEXT; + uniformMatrix2x3fvImplementation = glProgramUniformMatrix2x3fvEXT; + uniformMatrix3x2fvImplementation = glProgramUniformMatrix3x2fvEXT; + uniformMatrix2x4fvImplementation = glProgramUniformMatrix2x4fvEXT; + uniformMatrix4x2fvImplementation = glProgramUniformMatrix4x2fvEXT; + uniformMatrix3x4fvImplementation = glProgramUniformMatrix3x4fvEXT; + uniformMatrix4x3fvImplementation = glProgramUniformMatrix4x3fvEXT; #endif } else #endif { - uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform1ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform2ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform3ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform4ivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform1fvImplementation = &AbstractShaderProgram::uniform1fvImplementationDefault; + uniform2fvImplementation = &AbstractShaderProgram::uniform2fvImplementationDefault; + uniform3fvImplementation = &AbstractShaderProgram::uniform3fvImplementationDefault; + uniform4fvImplementation = &AbstractShaderProgram::uniform4fvImplementationDefault; + uniform1ivImplementation = &AbstractShaderProgram::uniform1ivImplementationDefault; + uniform2ivImplementation = &AbstractShaderProgram::uniform2ivImplementationDefault; + uniform3ivImplementation = &AbstractShaderProgram::uniform3ivImplementationDefault; + uniform4ivImplementation = &AbstractShaderProgram::uniform4ivImplementationDefault; #ifndef MAGNUM_TARGET_GLES2 - uniform1uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform2uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform3uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform4uivImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform1uivImplementation = &AbstractShaderProgram::uniform1uivImplementationDefault; + uniform2uivImplementation = &AbstractShaderProgram::uniform2uivImplementationDefault; + uniform3uivImplementation = &AbstractShaderProgram::uniform3uivImplementationDefault; + uniform4uivImplementation = &AbstractShaderProgram::uniform4uivImplementationDefault; #endif #ifndef MAGNUM_TARGET_GLES - uniform1dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniform4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniform1dvImplementation = &AbstractShaderProgram::uniform1dvImplementationDefault; + uniform2dvImplementation = &AbstractShaderProgram::uniform2dvImplementationDefault; + uniform3dvImplementation = &AbstractShaderProgram::uniform3dvImplementationDefault; + uniform4dvImplementation = &AbstractShaderProgram::uniform4dvImplementationDefault; #endif - uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix2fvImplementation = &AbstractShaderProgram::uniformMatrix2fvImplementationDefault; + uniformMatrix3fvImplementation = &AbstractShaderProgram::uniformMatrix3fvImplementationDefault; + uniformMatrix4fvImplementation = &AbstractShaderProgram::uniformMatrix4fvImplementationDefault; #ifndef MAGNUM_TARGET_GLES2 - uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix2x3fvImplementation = &AbstractShaderProgram::uniformMatrix2x3fvImplementationDefault; + uniformMatrix3x2fvImplementation = &AbstractShaderProgram::uniformMatrix3x2fvImplementationDefault; + uniformMatrix2x4fvImplementation = &AbstractShaderProgram::uniformMatrix2x4fvImplementationDefault; + uniformMatrix4x2fvImplementation = &AbstractShaderProgram::uniformMatrix4x2fvImplementationDefault; + uniformMatrix3x4fvImplementation = &AbstractShaderProgram::uniformMatrix3x4fvImplementationDefault; + uniformMatrix4x3fvImplementation = &AbstractShaderProgram::uniformMatrix4x3fvImplementationDefault; #endif #ifndef MAGNUM_TARGET_GLES - uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; - uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformImplementationDefault; + uniformMatrix2dvImplementation = &AbstractShaderProgram::uniformMatrix2dvImplementationDefault; + uniformMatrix3dvImplementation = &AbstractShaderProgram::uniformMatrix3dvImplementationDefault; + uniformMatrix4dvImplementation = &AbstractShaderProgram::uniformMatrix4dvImplementationDefault; + uniformMatrix2x3dvImplementation = &AbstractShaderProgram::uniformMatrix2x3dvImplementationDefault; + uniformMatrix3x2dvImplementation = &AbstractShaderProgram::uniformMatrix3x2dvImplementationDefault; + uniformMatrix2x4dvImplementation = &AbstractShaderProgram::uniformMatrix2x4dvImplementationDefault; + uniformMatrix4x2dvImplementation = &AbstractShaderProgram::uniformMatrix4x2dvImplementationDefault; + uniformMatrix3x4dvImplementation = &AbstractShaderProgram::uniformMatrix3x4dvImplementationDefault; + uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformMatrix4x3dvImplementationDefault; #endif } diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.h b/src/Magnum/GL/Implementation/ShaderProgramState.h index 92f68c5c7..5784b511d 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.h +++ b/src/Magnum/GL/Implementation/ShaderProgramState.h @@ -48,48 +48,48 @@ struct ShaderProgramState { #endif void(*cleanLogImplementation)(std::string&); - void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*); - void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*); - void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*); - void(AbstractShaderProgram::*uniform4fvImplementation)(GLint, GLsizei, const Math::Vector<4, GLfloat>*); - void(AbstractShaderProgram::*uniform1ivImplementation)(GLint, GLsizei, const GLint*); - void(AbstractShaderProgram::*uniform2ivImplementation)(GLint, GLsizei, const Math::Vector<2, GLint>*); - void(AbstractShaderProgram::*uniform3ivImplementation)(GLint, GLsizei, const Math::Vector<3, GLint>*); - void(AbstractShaderProgram::*uniform4ivImplementation)(GLint, GLsizei, const Math::Vector<4, GLint>*); + void(*uniform1fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); + void(*uniform2fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); + void(*uniform3fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); + void(*uniform4fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); + void(*uniform1ivImplementation)(GLuint, GLint, GLsizei, const GLint*); + void(*uniform2ivImplementation)(GLuint, GLint, GLsizei, const GLint*); + void(*uniform3ivImplementation)(GLuint, GLint, GLsizei, const GLint*); + void(*uniform4ivImplementation)(GLuint, GLint, GLsizei, const GLint*); #ifndef MAGNUM_TARGET_GLES2 - void(AbstractShaderProgram::*uniform1uivImplementation)(GLint, GLsizei, const GLuint*); - void(AbstractShaderProgram::*uniform2uivImplementation)(GLint, GLsizei, const Math::Vector<2, GLuint>*); - void(AbstractShaderProgram::*uniform3uivImplementation)(GLint, GLsizei, const Math::Vector<3, GLuint>*); - void(AbstractShaderProgram::*uniform4uivImplementation)(GLint, GLsizei, const Math::Vector<4, GLuint>*); + void(*uniform1uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); + void(*uniform2uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); + void(*uniform3uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); + void(*uniform4uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); #endif #ifndef MAGNUM_TARGET_GLES - void(AbstractShaderProgram::*uniform1dvImplementation)(GLint, GLsizei, const GLdouble*); - void(AbstractShaderProgram::*uniform2dvImplementation)(GLint, GLsizei, const Math::Vector<2, GLdouble>*); - void(AbstractShaderProgram::*uniform3dvImplementation)(GLint, GLsizei, const Math::Vector<3, GLdouble>*); - void(AbstractShaderProgram::*uniform4dvImplementation)(GLint, GLsizei, const Math::Vector<4, GLdouble>*); + void(*uniform1dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); + void(*uniform2dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); + void(*uniform3dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); + void(*uniform4dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); #endif - void(AbstractShaderProgram::*uniformMatrix2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLfloat>*); - void(AbstractShaderProgram::*uniformMatrix3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLfloat>*); - void(AbstractShaderProgram::*uniformMatrix4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLfloat>*); + void(*uniformMatrix2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(*uniformMatrix3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(*uniformMatrix4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); #ifndef MAGNUM_TARGET_GLES2 - void(AbstractShaderProgram::*uniformMatrix2x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLfloat>*); - void(AbstractShaderProgram::*uniformMatrix3x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLfloat>*); - void(AbstractShaderProgram::*uniformMatrix2x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLfloat>*); - void(AbstractShaderProgram::*uniformMatrix4x2fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLfloat>*); - void(AbstractShaderProgram::*uniformMatrix3x4fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLfloat>*); - void(AbstractShaderProgram::*uniformMatrix4x3fvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLfloat>*); + void(*uniformMatrix2x3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(*uniformMatrix3x2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(*uniformMatrix2x4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(*uniformMatrix4x2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(*uniformMatrix3x4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(*uniformMatrix4x3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); #endif #ifndef MAGNUM_TARGET_GLES - void(AbstractShaderProgram::*uniformMatrix2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 2, GLdouble>*); - void(AbstractShaderProgram::*uniformMatrix3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 3, GLdouble>*); - void(AbstractShaderProgram::*uniformMatrix4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 4, GLdouble>*); - void(AbstractShaderProgram::*uniformMatrix2x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 3, GLdouble>*); - void(AbstractShaderProgram::*uniformMatrix3x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 2, GLdouble>*); - void(AbstractShaderProgram::*uniformMatrix2x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<2, 4, GLdouble>*); - void(AbstractShaderProgram::*uniformMatrix4x2dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 2, GLdouble>*); - void(AbstractShaderProgram::*uniformMatrix3x4dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<3, 4, GLdouble>*); - void(AbstractShaderProgram::*uniformMatrix4x3dvImplementation)(GLint, GLsizei, const Math::RectangularMatrix<4, 3, GLdouble>*); + void(*uniformMatrix2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(*uniformMatrix3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(*uniformMatrix4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(*uniformMatrix2x3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(*uniformMatrix3x2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(*uniformMatrix2x4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(*uniformMatrix4x2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(*uniformMatrix3x4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(*uniformMatrix4x3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); #endif /* Currently used program */ From 490392b143eba855daa2a99e523567746e82e557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 2 Mar 2021 16:11:05 +0100 Subject: [PATCH 055/161] GL: call glUniform() directly on WebGL. There are no SSO / DSA extensions on that platform, so it doesn't make sense to do this extra indirection. Saves another kilobyte (237 -> 236 kB) in WebGL 2 magnum-gl-info.wasm. --- src/Magnum/GL/AbstractShaderProgram.cpp | 210 ++++++++++++++++-- .../GL/Implementation/ShaderProgramState.cpp | 4 +- .../GL/Implementation/ShaderProgramState.h | 2 + 3 files changed, 194 insertions(+), 22 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index 752c0b58b..5f228b827 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -565,72 +565,136 @@ UnsignedInt AbstractShaderProgram::uniformBlockIndexInternal(const Containers::A #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - Context::current().state().shaderProgram.uniform1fvImplementation(_id, location, values.size(), values.data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform1fvImplementation + #else + uniform1fvImplementationDefault + #endif + (_id, location, values.size(), values.data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform1fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLfloat* const values) { use(id); glUniform1fv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform2fvImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform2fvImplementation + #else + uniform2fvImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform2fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLfloat* const values) { use(id); glUniform2fv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform3fvImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform3fvImplementation + #else + uniform3fvImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform3fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLfloat* const values) { use(id); glUniform3fv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform4fvImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform4fvImplementation + #else + uniform4fvImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform4fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLfloat* const values) { use(id); glUniform4fv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - Context::current().state().shaderProgram.uniform1ivImplementation(_id, location, values.size(), values.data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform1ivImplementation + #else + uniform1ivImplementationDefault + #endif + (_id, location, values.size(), values.data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform1ivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLint* values) { use(id); glUniform1iv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform2ivImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform2ivImplementation + #else + uniform2ivImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform2ivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLint* const values) { use(id); glUniform2iv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform3ivImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform3ivImplementation + #else + uniform3ivImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform3ivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLint* const values) { use(id); glUniform3iv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform4ivImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform4ivImplementation + #else + uniform4ivImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform4ivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLint* const values) { use(id); glUniform4iv(location, count, values); @@ -638,36 +702,68 @@ void AbstractShaderProgram::uniform4ivImplementationDefault(const GLuint id, con #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView values) { - Context::current().state().shaderProgram.uniform1uivImplementation(_id, location, values.size(), values.data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform1uivImplementation + #else + uniform1uivImplementationDefault + #endif + (_id, location, values.size(), values.data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform1uivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLuint* const values) { use(id); glUniform1uiv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform2uivImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform2uivImplementation + #else + uniform2uivImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform2uivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLuint* const values) { use(id); glUniform2uiv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform3uivImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform3uivImplementation + #else + uniform3uivImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform3uivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLuint* const values) { use(id); glUniform3uiv(location, count, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniform4uivImplementation(_id, location, values.size(), values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniform4uivImplementation + #else + uniform4uivImplementationDefault + #endif + (_id, location, values.size(), values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniform4uivImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLuint* const values) { use(id); glUniform4uiv(location, count, values); @@ -713,27 +809,51 @@ void AbstractShaderProgram::uniform4dvImplementationDefault(const GLuint id, con #endif void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix2fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix2fvImplementation + #else + uniformMatrix2fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix2fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix2fv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix3fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix3fvImplementation + #else + uniformMatrix3fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix3fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix3fv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix4fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix4fvImplementation + #else + uniformMatrix4fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix4fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix4fv(location, count, transpose, values); @@ -741,54 +861,102 @@ void AbstractShaderProgram::uniformMatrix4fvImplementationDefault(const GLuint i #ifndef MAGNUM_TARGET_GLES2 void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix2x3fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix2x3fvImplementation + #else + uniformMatrix2x3fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix2x3fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix2x3fv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix3x2fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix3x2fvImplementation + #else + uniformMatrix3x2fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix3x2fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix3x2fv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix2x4fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix2x4fvImplementation + #else + uniformMatrix2x4fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix2x4fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix2x4fv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix4x2fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix4x2fvImplementation + #else + uniformMatrix4x2fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix4x2fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix4x2fv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix3x4fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix3x4fvImplementation + #else + uniformMatrix3x4fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix3x4fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix3x4fv(location, count, transpose, values); } void AbstractShaderProgram::setUniform(const Int location, const Containers::ArrayView> values) { - Context::current().state().shaderProgram.uniformMatrix4x3fvImplementation(_id, location, values.size(), GL_FALSE, values.data()->data()); + #ifndef MAGNUM_TARGET_WEBGL + Context::current().state().shaderProgram.uniformMatrix4x3fvImplementation + #else + uniformMatrix4x3fvImplementationDefault + #endif + (_id, location, values.size(), GL_FALSE, values.data()->data()); } +#ifdef MAGNUM_TARGET_WEBGL +inline +#endif void AbstractShaderProgram::uniformMatrix4x3fvImplementationDefault(const GLuint id, const GLint location, const GLsizei count, const GLboolean transpose, const GLfloat* const values) { use(id); glUniformMatrix4x3fv(location, count, transpose, values); diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.cpp b/src/Magnum/GL/Implementation/ShaderProgramState.cpp index 74ab8d6f0..3d47d7215 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.cpp +++ b/src/Magnum/GL/Implementation/ShaderProgramState.cpp @@ -78,7 +78,8 @@ ShaderProgramState::ShaderProgramState(Context& context, Containers::StaticArray cleanLogImplementation = &AbstractShaderProgram::cleanLogImplementationNoOp; } - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + #ifndef MAGNUM_TARGET_WEBGL + #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES if(context.isExtensionSupported()) #else @@ -210,6 +211,7 @@ ShaderProgramState::ShaderProgramState(Context& context, Containers::StaticArray uniformMatrix4x3dvImplementation = &AbstractShaderProgram::uniformMatrix4x3dvImplementationDefault; #endif } + #endif #ifdef MAGNUM_TARGET_WEBGL static_cast(context); diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.h b/src/Magnum/GL/Implementation/ShaderProgramState.h index 5784b511d..4793433bd 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.h +++ b/src/Magnum/GL/Implementation/ShaderProgramState.h @@ -48,6 +48,7 @@ struct ShaderProgramState { #endif void(*cleanLogImplementation)(std::string&); + #ifndef MAGNUM_TARGET_WEBGL void(*uniform1fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); void(*uniform2fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); void(*uniform3fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); @@ -91,6 +92,7 @@ struct ShaderProgramState { void(*uniformMatrix3x4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); void(*uniformMatrix4x3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); #endif + #endif /* Currently used program */ GLuint current; From 7c07c6fdc6dbcd430379ae078c6088b8a57667da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 3 Mar 2021 14:31:23 +0100 Subject: [PATCH 056/161] GL: make FramebufferClearColor searchable under GL keywords. 'cuz I was writing some raw GL for Emscripten tests and arrived at glClear(GL_COLOR); without having any suspicion that this is just TOTALLY WRONG. Same would go for Vulkan few years ahead when I'm so used to the Magnum wrappers that I forget what the common pitfalls are. --- src/Magnum/GL/AbstractFramebuffer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magnum/GL/AbstractFramebuffer.h b/src/Magnum/GL/AbstractFramebuffer.h index 73e1a030b..c03a5c0b3 100644 --- a/src/Magnum/GL/AbstractFramebuffer.h +++ b/src/Magnum/GL/AbstractFramebuffer.h @@ -41,6 +41,7 @@ namespace Magnum { namespace GL { @brief Mask for framebuffer clearing @see @ref AbstractFramebuffer, @ref FramebufferClearMask +@m_enum_values_as_keywords */ enum class FramebufferClear: GLbitfield { Color = GL_COLOR_BUFFER_BIT, /**< Color buffer */ From b8e21b8b21da85fea52cf5d37cda5454d9ca0334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 3 Mar 2021 14:43:54 +0100 Subject: [PATCH 057/161] GL: make the new setUniform() code paths work on 32bit Windows. The GL API uses the __stdcall calling convention but the default is __cdecl. This distinction is not on 64bit anymore and there it's the same. --- src/Magnum/GL/AbstractShaderProgram.h | 68 +++++++++---------- .../GL/Implementation/ShaderProgramState.h | 68 +++++++++---------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.h b/src/Magnum/GL/AbstractShaderProgram.h index 9f17ffdf7..fe54fae93 100644 --- a/src/Magnum/GL/AbstractShaderProgram.h +++ b/src/Magnum/GL/AbstractShaderProgram.h @@ -1369,48 +1369,48 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject { signature matching the DSA APIs. On DSA-enabled platforms the glProgramUniform*() functions are used directly, otherwise these all use() the shader first and then call the old-style API. */ - MAGNUM_GL_LOCAL static void uniform1fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniform2fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniform3fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniform4fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniform1ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); - MAGNUM_GL_LOCAL static void uniform2ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); - MAGNUM_GL_LOCAL static void uniform3ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); - MAGNUM_GL_LOCAL static void uniform4ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform1fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform2fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform3fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform4fvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform1ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform2ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform3ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform4ivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLint* values); #ifndef MAGNUM_TARGET_GLES2 - MAGNUM_GL_LOCAL static void uniform1uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); - MAGNUM_GL_LOCAL static void uniform2uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); - MAGNUM_GL_LOCAL static void uniform3uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); - MAGNUM_GL_LOCAL static void uniform4uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform1uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform2uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform3uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform4uivImplementationDefault(GLuint id, GLint location, GLsizei count, const GLuint* values); #endif #ifndef MAGNUM_TARGET_GLES - MAGNUM_GL_LOCAL static void uniform1dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniform2dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniform3dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniform4dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform1dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform2dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform3dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniform4dvImplementationDefault(GLuint id, GLint location, GLsizei count, const GLdouble* values); #endif - MAGNUM_GL_LOCAL static void uniformMatrix2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniformMatrix3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniformMatrix4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); #ifndef MAGNUM_TARGET_GLES2 - MAGNUM_GL_LOCAL static void uniformMatrix2x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniformMatrix3x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniformMatrix2x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniformMatrix4x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniformMatrix3x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); - MAGNUM_GL_LOCAL static void uniformMatrix4x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x2fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x4fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x3fvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLfloat* values); #endif #ifndef MAGNUM_TARGET_GLES - MAGNUM_GL_LOCAL static void uniformMatrix2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniformMatrix3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniformMatrix4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniformMatrix2x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniformMatrix3x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniformMatrix2x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniformMatrix4x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniformMatrix3x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); - MAGNUM_GL_LOCAL static void uniformMatrix4x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix2x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x2dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix3x4dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); + MAGNUM_GL_LOCAL static void APIENTRY uniformMatrix4x3dvImplementationDefault(GLuint id, GLint location, GLsizei count, GLboolean transpose, const GLdouble* values); #endif GLuint _id; diff --git a/src/Magnum/GL/Implementation/ShaderProgramState.h b/src/Magnum/GL/Implementation/ShaderProgramState.h index 4793433bd..dc686e174 100644 --- a/src/Magnum/GL/Implementation/ShaderProgramState.h +++ b/src/Magnum/GL/Implementation/ShaderProgramState.h @@ -49,48 +49,48 @@ struct ShaderProgramState { void(*cleanLogImplementation)(std::string&); #ifndef MAGNUM_TARGET_WEBGL - void(*uniform1fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); - void(*uniform2fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); - void(*uniform3fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); - void(*uniform4fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); - void(*uniform1ivImplementation)(GLuint, GLint, GLsizei, const GLint*); - void(*uniform2ivImplementation)(GLuint, GLint, GLsizei, const GLint*); - void(*uniform3ivImplementation)(GLuint, GLint, GLsizei, const GLint*); - void(*uniform4ivImplementation)(GLuint, GLint, GLsizei, const GLint*); + void(APIENTRY *uniform1fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); + void(APIENTRY *uniform2fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); + void(APIENTRY *uniform3fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); + void(APIENTRY *uniform4fvImplementation)(GLuint, GLint, GLsizei, const GLfloat*); + void(APIENTRY *uniform1ivImplementation)(GLuint, GLint, GLsizei, const GLint*); + void(APIENTRY *uniform2ivImplementation)(GLuint, GLint, GLsizei, const GLint*); + void(APIENTRY *uniform3ivImplementation)(GLuint, GLint, GLsizei, const GLint*); + void(APIENTRY *uniform4ivImplementation)(GLuint, GLint, GLsizei, const GLint*); #ifndef MAGNUM_TARGET_GLES2 - void(*uniform1uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); - void(*uniform2uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); - void(*uniform3uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); - void(*uniform4uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); + void(APIENTRY *uniform1uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); + void(APIENTRY *uniform2uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); + void(APIENTRY *uniform3uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); + void(APIENTRY *uniform4uivImplementation)(GLuint, GLint, GLsizei, const GLuint*); #endif #ifndef MAGNUM_TARGET_GLES - void(*uniform1dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); - void(*uniform2dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); - void(*uniform3dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); - void(*uniform4dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); + void(APIENTRY *uniform1dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); + void(APIENTRY *uniform2dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); + void(APIENTRY *uniform3dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); + void(APIENTRY *uniform4dvImplementation)(GLuint, GLint, GLsizei, const GLdouble*); #endif - void(*uniformMatrix2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); - void(*uniformMatrix3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); - void(*uniformMatrix4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); #ifndef MAGNUM_TARGET_GLES2 - void(*uniformMatrix2x3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); - void(*uniformMatrix3x2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); - void(*uniformMatrix2x4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); - void(*uniformMatrix4x2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); - void(*uniformMatrix3x4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); - void(*uniformMatrix4x3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix2x3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix3x2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix2x4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix4x2fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix3x4fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); + void(APIENTRY *uniformMatrix4x3fvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLfloat*); #endif #ifndef MAGNUM_TARGET_GLES - void(*uniformMatrix2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); - void(*uniformMatrix3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); - void(*uniformMatrix4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); - void(*uniformMatrix2x3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); - void(*uniformMatrix3x2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); - void(*uniformMatrix2x4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); - void(*uniformMatrix4x2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); - void(*uniformMatrix3x4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); - void(*uniformMatrix4x3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix2x3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix3x2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix2x4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix4x2dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix3x4dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); + void(APIENTRY *uniformMatrix4x3dvImplementation)(GLuint, GLint, GLsizei, GLboolean, const GLdouble*); #endif #endif From 87088296d83993199f21b41b08d19882ef60c259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 3 Mar 2021 14:46:14 +0100 Subject: [PATCH 058/161] GL: this TimeQuery test was just dumb. Ah the good old times where my brain was not overflowing with unnecessarily deep knowledge about how GPUs (and OpenGL drivers in particular) work. Nope, switching a blend state and calling glFinish() won't generate any GPU work, that will be all deferred until there's something to be actually drawn, cleared or copied. --- src/Magnum/GL/Test/TimeQueryGLTest.cpp | 60 ++++++++++++++++++++------ 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/src/Magnum/GL/Test/TimeQueryGLTest.cpp b/src/Magnum/GL/Test/TimeQueryGLTest.cpp index e50768b4c..9f1e48569 100644 --- a/src/Magnum/GL/Test/TimeQueryGLTest.cpp +++ b/src/Magnum/GL/Test/TimeQueryGLTest.cpp @@ -27,7 +27,10 @@ #include "Magnum/GL/Context.h" #include "Magnum/GL/Extensions.h" +#include "Magnum/GL/Framebuffer.h" #include "Magnum/GL/OpenGLTester.h" +#include "Magnum/GL/Renderbuffer.h" +#include "Magnum/GL/RenderbufferFormat.h" #include "Magnum/GL/TimeQuery.h" namespace Magnum { namespace GL { namespace Test { namespace { @@ -105,22 +108,37 @@ void TimeQueryGLTest::queryTime() { CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available")); #endif + Renderbuffer renderbuffer; + renderbuffer.setStorage( + #ifndef MAGNUM_TARGET_GLES2 + RenderbufferFormat::RGBA8, + #else + RenderbufferFormat::RGBA4, + #endif + Vector2i(32)); + + Framebuffer framebuffer({{}, Vector2i{256, 256}}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); + + /* A query with nothing inside should be almost zero */ TimeQuery q1{TimeQuery::Target::TimeElapsed}; q1.begin(); q1.end(); - const auto result1 = q1.result(); - + const auto result1 = q1.result(); MAGNUM_VERIFY_NO_GL_ERROR(); + Debug{} << "Doing nothing took" << result1/1.0e6f << "ms"; + CORRADE_COMPARE_AS(result1, 0, TestSuite::Compare::GreaterOrEqual); + /* A query with a clear inside should be nonzero and larger than nothing */ TimeQuery q2{TimeQuery::Target::TimeElapsed}; q2.begin(); - Renderer::enable(Renderer::Feature::Blending); - Renderer::finish(); + framebuffer.clear(FramebufferClear::Color); q2.end(); - const auto result2 = q2.result(); - + const auto result2 = q2.result(); MAGNUM_VERIFY_NO_GL_ERROR(); - CORRADE_COMPARE_AS(result2, result1, TestSuite::Compare::GreaterOrEqual); + Debug{} << "Clear took" << result2/1.0e6f << "ms"; + CORRADE_VERIFY(result2); + CORRADE_COMPARE_AS(result2, result1, TestSuite::Compare::Greater); } void TimeQueryGLTest::queryTimestamp() { @@ -135,6 +153,18 @@ void TimeQueryGLTest::queryTimestamp() { CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available")); #endif + Renderbuffer renderbuffer; + renderbuffer.setStorage( + #ifndef MAGNUM_TARGET_GLES2 + RenderbufferFormat::RGBA8, + #else + RenderbufferFormat::RGBA4, + #endif + Vector2i(32)); + + Framebuffer framebuffer({{}, Vector2i{256, 256}}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); + TimeQuery q1{TimeQuery::Target::Timestamp}, q2{TimeQuery::Target::Timestamp}, q{TimeQuery::Target::TimeElapsed}; @@ -142,19 +172,23 @@ void TimeQueryGLTest::queryTimestamp() { q1.timestamp(); q.begin(); - Renderer::enable(Renderer::Feature::Blending); - Renderer::finish(); + framebuffer.clear(FramebufferClear::Color); q.end(); q2.timestamp(); - const auto result = q.result(); + const auto result = q.result(); const auto result1 = q1.result(); const auto result2 = q2.result(); - MAGNUM_VERIFY_NO_GL_ERROR(); - CORRADE_COMPARE_AS(result2, result1, TestSuite::Compare::GreaterOrEqual); - CORRADE_COMPARE_AS(result2 - result1, result, TestSuite::Compare::GreaterOrEqual); + + Debug{} << "Clear took" << result/1.0e6f << "ms, timestamp difference is" + << (result2 - result1)/1.0e6f << "ms"; + + /* The timestamps should be monotonically increasing and the difference + slightly larger than the elapsed time because these are outside of it */ + CORRADE_COMPARE_AS(result2, result1, TestSuite::Compare::Greater); + CORRADE_COMPARE_AS(result2 - result1, result, TestSuite::Compare::Greater); } }}}} From beecb8fb82e74e42149a17903cd0f2a387d21e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 3 Mar 2021 17:29:58 +0100 Subject: [PATCH 059/161] Shaders: fix copypaste errors in Phong setter docs. --- doc/changelog.dox | 1 + src/Magnum/Shaders/Phong.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 9de2513ae..9d4adc44c 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -550,6 +550,7 @@ See also: - Added a note about MinGW GCC and Clang ABI incompatibility to @ref platforms-windows "Windows platform docs" (see [mosra/magnum#227](https://github.com/mosra/magnum/issues/227) and [mosra/magnum#439](https://github.com/mosra/magnum/issues/439)) +- Various documentation fixes (see [mosra/magnum#492](https://github.com/mosra/magnum/issues/492)) @section changelog-2020-06 2020.06 diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index 93eabeb2e..b59537083 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -917,7 +917,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { #endif /** - * @brief Set position for given light + * @brief Set color for given light * @return Reference to self (for method chaining) * @m_since_latest * @@ -967,7 +967,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { Phong& setLightSpecularColors(std::initializer_list colors); /** - * @brief Set position for given light + * @brief Set specular color for given light * @return Reference to self (for method chaining) * @m_since_latest * From 3ad398369aaed2e4f0fe3abdc37f3e507154b472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 3 Mar 2021 17:30:11 +0100 Subject: [PATCH 060/161] doc: update changelog. --- doc/changelog.dox | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/changelog.dox b/doc/changelog.dox index 9d4adc44c..059d56ddb 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -313,6 +313,8 @@ See also: - The Homebrew package now uses `std_cmake_args` instead of hardcoded build type and install prefix, which resolves certain build issues (see [mosra/homebrew-magnum#6](https://github.com/mosra/homebrew-magnum/pull/6)) +- Various changes to Vcpkg packages to account for newly added libraries and + plugin interfaces ([mosra/magnum#485](https://github.com/mosra/magnum/issues/485)) @subsection changelog-latest-bugfixes Bug fixes From 62628beac97726468351a1485b01caa5662a0d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 27 Feb 2021 14:48:45 +0100 Subject: [PATCH 061/161] modules: make it possible to use SDL2 as a CMake subproject. --- doc/changelog.dox | 3 ++ modules/FindSDL2.cmake | 57 +++++++++++++++++++++++++++ src/Magnum/Platform/Sdl2Application.h | 42 ++++++++++++++++++-- 3 files changed, 98 insertions(+), 4 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 059d56ddb..4b9ac12b6 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -315,6 +315,9 @@ See also: [mosra/homebrew-magnum#6](https://github.com/mosra/homebrew-magnum/pull/6)) - Various changes to Vcpkg packages to account for newly added libraries and plugin interfaces ([mosra/magnum#485](https://github.com/mosra/magnum/issues/485)) +- The `FindSDL2.cmake` module was updated to allow using SDL2 as a + subproject. See the @ref Platform-Sdl2Application-usage "Platform::Sdl2Application docs" + for more information. See also [mosra/magnum#496](https://github.com/mosra/magnum/issues/496). @subsection changelog-latest-bugfixes Bug fixes diff --git a/modules/FindSDL2.cmake b/modules/FindSDL2.cmake index 622258867..54844d696 100644 --- a/modules/FindSDL2.cmake +++ b/modules/FindSDL2.cmake @@ -42,6 +42,63 @@ # DEALINGS IN THE SOFTWARE. # +# If we have a CMake subproject, use the targets directly. I'd prefer the +# static variant, however SDL2 defines its own SDL2::SDL2 alias for only the +# dynamic variant since https://github.com/libsdl-org/SDL/pull/4074 and so I'm +# forced to use that, if available. +if(TARGET SDL2) + # In case we don't have https://github.com/libsdl-org/SDL/pull/4074 yet, + # do the alias ourselves. + if(NOT TARGET SDL2::SDL2) + # Aliases of (global) targets are only supported in CMake 3.11, so we + # work around it by this. This is easier than fetching all possible + # properties (which are impossible to track of) and then attempting to + # rebuild them into a new target. + add_library(SDL2::SDL2 INTERFACE IMPORTED) + set_target_properties(SDL2::SDL2 PROPERTIES INTERFACE_LINK_LIBRARIES SDL2) + endif() + + # Just to make FPHSA print some meaningful location, nothing else. Not + # using the INTERFACE_INCLUDE_DIRECTORIES as that contains + # $ + +@m_class{m-note m-warning} + +@par + While SDL itself, being a C project, builds quite fast, when using it as a + CMake subproject be prepared that it will *significantly* increase the + CMake configure time due to excessive platform checks, and pollute the + CMake option list with a lot of unprefixed SDL-specific options. + If no other application is requested, you can also use the generic `Magnum::Application` alias to simplify porting. Again, see @ref building and @ref cmake for more information. From 41dc0dffff74eda3d431bbb438a65db7e315fc22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Mar 2021 13:24:17 +0100 Subject: [PATCH 062/161] ShaderTools: --{input,output}-format is a thing now. --- src/Magnum/ShaderTools/AbstractConverter.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Magnum/ShaderTools/AbstractConverter.h b/src/Magnum/ShaderTools/AbstractConverter.h index 5dd8b9694..a4030950d 100644 --- a/src/Magnum/ShaderTools/AbstractConverter.h +++ b/src/Magnum/ShaderTools/AbstractConverter.h @@ -590,9 +590,9 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac * @ref linkDataToData(), @ref linkDataToFile(), @ref linkFilesToFile() * or @ref linkFilesToData() call will fail. * - * The @p version parameter corresponds to the `--input-version` option - * in @ref magnum-shaderconverter "magnum-shaderconverter", the - * @p format isn't currently exposed there. + * The @p format parameter corresponds to the `--input-format` option + * in @ref magnum-shaderconverter "magnum-shaderconverter", + * @p version to `--input-version`. * @see @ref setOutputFormat() */ #ifdef DOXYGEN_GENERATING_OUTPUT @@ -614,9 +614,9 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac * @ref linkDataToData(), @ref linkDataToFile(), @ref linkFilesToFile() * or @ref linkFilesToData() call will fail. * - * The @p version parameter corresponds to the `--output-version` - * option in @ref magnum-shaderconverter "magnum-shaderconverter", the - * @p format isn't currently exposed there. + * The @p format parameter corresponds to the `--output-format` option + * in @ref magnum-shaderconverter "magnum-shaderconverter", + * @p version to `--output-version`. * @see @ref setInputFormat() */ #ifdef DOXYGEN_GENERATING_OUTPUT From e3c72b36ee1cb444216ec0493ee1de96eb993def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Mar 2021 14:27:20 +0100 Subject: [PATCH 063/161] Trade: doc++ --- src/Magnum/Trade/AbstractImageConverter.h | 6 ++++++ src/Magnum/Trade/AbstractImporter.h | 10 ++++++++++ src/Magnum/Trade/AbstractSceneConverter.h | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index 5871146e4..63ea0f380 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -110,6 +110,9 @@ enum class ImageConverterFlag: UnsignedByte { * Print verbose diagnostic during conversion. By default the converter * only prints messages on error or when some operation might cause * unexpected data modification or loss. + * + * Corresponds to the `-v` / `--verbose` option in + * @ref magnum-imageconverter "magnum-imageconverter". */ Verbose = 1 << 0 @@ -260,6 +263,9 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract * Some flags can be set only if the converter supports particular * features, see documentation of each @ref ImageConverterFlag for more * information. By default no flags are set. + * + * Corresponds to the `-v` / `--verbose` option in + * @ref magnum-imageconverter "magnum-imageconverter". */ void setFlags(ImageConverterFlags flags); diff --git a/src/Magnum/Trade/AbstractImporter.h b/src/Magnum/Trade/AbstractImporter.h index 0fc844add..c031a1c95 100644 --- a/src/Magnum/Trade/AbstractImporter.h +++ b/src/Magnum/Trade/AbstractImporter.h @@ -101,6 +101,11 @@ enum class ImporterFlag: UnsignedByte { * Print verbose diagnostic during import. By default the importer only * prints messages on error or when some operation might cause unexpected * data modification or loss. + * + * Corresponds to the `-v` / `--verbose` option in + * @ref magnum-imageconverter "magnum-imageconverter", + * @ref magnum-sceneconverter "magnum-sceneconverter" and + * @ref magnum-player "magnum-player". */ Verbose = 1 << 0, @@ -393,6 +398,11 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi * opened. Some flags can be set only if the importer supports * particular features, see documentation of each @ref ImporterFlag for * more information. By default no flags are set. + * + * Corresponds to the `-v` / `--verbose` option in + * @ref magnum-imageconverter "magnum-imageconverter", + * @ref magnum-sceneconverter "magnum-sceneconverter" and + * @ref magnum-player "magnum-player". */ void setFlags(ImporterFlags flags); diff --git a/src/Magnum/Trade/AbstractSceneConverter.h b/src/Magnum/Trade/AbstractSceneConverter.h index 875331794..e28d0edf9 100644 --- a/src/Magnum/Trade/AbstractSceneConverter.h +++ b/src/Magnum/Trade/AbstractSceneConverter.h @@ -98,6 +98,9 @@ enum class SceneConverterFlag: UnsignedByte { * Print verbose diagnostic during conversion. By default the converter * only prints messages on error or when some operation might cause * unexpected data modification or loss. + * + * Corresponds to the `-v` / `--verbose` option in + * @ref magnum-sceneconverter "magnum-sceneconverter". */ Verbose = 1 << 0 @@ -229,6 +232,9 @@ class MAGNUM_TRADE_EXPORT AbstractSceneConverter: public PluginManager::Abstract * Some flags can be set only if the converter supports particular * features, see documentation of each @ref SceneConverterFlag for more * information. By default no flags are set. + * + * Corresponds to the `-v` / `--verbose` option in + * @ref magnum-sceneconverter "magnum-sceneconverter". */ void setFlags(SceneConverterFlags flags); From 29ac7b5a4dd430b8491e48eb5ea49a15630b09bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Mar 2021 14:27:53 +0100 Subject: [PATCH 064/161] Trade,ShaderTools: add addFlags() / clearFlags() to all plugin interfaces. There will be Flag::FlipY for images at some point, enabled by default for compatibility with existing GL code, and so it makes sense to start discouraging setFlags() as early as possible to avoid people resetting the default by accident. Also update the imageconverter, sceneconverter and shaderconverter utils to use these instead of setFlags(). --- doc/changelog.dox | 5 ++++ src/Magnum/MeshTools/sceneconverter.cpp | 4 ++-- src/Magnum/ShaderTools/AbstractConverter.cpp | 8 +++++++ src/Magnum/ShaderTools/AbstractConverter.h | 24 ++++++++++++++++++- .../Test/AbstractConverterTest.cpp | 11 ++++++++- src/Magnum/ShaderTools/shaderconverter.cpp | 2 +- src/Magnum/Trade/AbstractImageConverter.cpp | 8 +++++++ src/Magnum/Trade/AbstractImageConverter.h | 24 ++++++++++++++++++- src/Magnum/Trade/AbstractImporter.cpp | 8 +++++++ src/Magnum/Trade/AbstractImporter.h | 24 ++++++++++++++++++- src/Magnum/Trade/AbstractSceneConverter.cpp | 8 +++++++ src/Magnum/Trade/AbstractSceneConverter.h | 24 ++++++++++++++++++- .../Trade/Test/AbstractImageConverterTest.cpp | 11 ++++++++- .../Trade/Test/AbstractImporterTest.cpp | 19 +++++++++++++-- .../Trade/Test/AbstractSceneConverterTest.cpp | 11 ++++++++- src/Magnum/Trade/imageconverter.cpp | 4 ++-- 16 files changed, 181 insertions(+), 14 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 4b9ac12b6..9c425ef7b 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -173,6 +173,11 @@ See also: well as support in @ref Trade::AnySceneImporter "AnySceneImporter" - @ref Trade::LightData got extended to support light attenuation and range parameters as well and spot light inner and outer angle +- @ref Trade::AbstractImporter, @ref Trade::AbstractImageConverter and + @ref Trade::AbstractSceneConverter now has @relativeref{Trade::AbstractImporter,addFlags()} and + @relativeref{Trade::AbstractImporter,clearFlags()} convenience helpers that + are encouraged over @relativeref{Trade::AbstractImporter,setFlags()} as it + avoid accidentally clearing default flags potentially added in the future. @subsubsection changelog-latest-new-vk Vk library diff --git a/src/Magnum/MeshTools/sceneconverter.cpp b/src/Magnum/MeshTools/sceneconverter.cpp index 8e1676c3b..0bdbc45cb 100644 --- a/src/Magnum/MeshTools/sceneconverter.cpp +++ b/src/Magnum/MeshTools/sceneconverter.cpp @@ -261,7 +261,7 @@ used.)") } /* Set options, if passed */ - if(args.isSet("verbose")) importer->setFlags(Trade::ImporterFlag::Verbose); + if(args.isSet("verbose")) importer->addFlags(Trade::ImporterFlag::Verbose); Implementation::setOptions(*importer, args.value("importer-options")); std::chrono::high_resolution_clock::duration importTime; @@ -766,7 +766,7 @@ used.)") } /* Set options, if passed */ - if(args.isSet("verbose")) converter->setFlags(Trade::SceneConverterFlag::Verbose); + if(args.isSet("verbose")) converter->addFlags(Trade::SceneConverterFlag::Verbose); if(i < args.arrayValueCount("converter-options")) Implementation::setOptions(*converter, args.arrayValue("converter-options", i)); diff --git a/src/Magnum/ShaderTools/AbstractConverter.cpp b/src/Magnum/ShaderTools/AbstractConverter.cpp index 0443bb7db..e43a4ee79 100644 --- a/src/Magnum/ShaderTools/AbstractConverter.cpp +++ b/src/Magnum/ShaderTools/AbstractConverter.cpp @@ -95,6 +95,14 @@ void AbstractConverter::setFlags(const ConverterFlags flags) { void AbstractConverter::doSetFlags(ConverterFlags) {} +void AbstractConverter::addFlags(ConverterFlags flags) { + setFlags(_flags|flags); +} + +void AbstractConverter::clearFlags(ConverterFlags flags) { + setFlags(_flags & ~flags); +} + void AbstractConverter::setInputFileCallback(Containers::Optional>(*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, diff --git a/src/Magnum/ShaderTools/AbstractConverter.h b/src/Magnum/ShaderTools/AbstractConverter.h index a4030950d..61ff94112 100644 --- a/src/Magnum/ShaderTools/AbstractConverter.h +++ b/src/Magnum/ShaderTools/AbstractConverter.h @@ -471,7 +471,9 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac * * 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. + * information. By default no flags are set. To avoid clearing + * potential future default flags by accident, prefer to use + * @ref addFlags() and @ref clearFlags() instead. * * Corresponds to the `-q` / `--quiet`, `-v` / `--verbose`, * `--warning-as-error` and `-E` / `--preprocess-only` options @@ -479,6 +481,26 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac */ void setFlags(ConverterFlags flags); + /** + * @brief Add converter flags + * @m_since_latest + * + * Calls @ref setFlags() with the existing flags ORed with @p flags. + * Useful for preserving the defaults. + * @see @ref clearFlags() + */ + void addFlags(ConverterFlags flags); + + /** + * @brief Clear converter flags + * @m_since_latest + * + * Calls @ref setFlags() with the existing flags ANDed with inverse of + * @p flags. Useful for removing default flags. + * @see @ref addFlags() + */ + void clearFlags(ConverterFlags flags); + /** * @brief Input file callback function * diff --git a/src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp b/src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp index 56b75ac64..8d87988a3 100644 --- a/src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp +++ b/src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp @@ -359,12 +359,21 @@ void AbstractConverterTest::setFlags() { ConverterFlags _flags; } converter; - CORRADE_COMPARE(converter.flags(), ConverterFlags{}); CORRADE_COMPARE(converter._flags, ConverterFlags{}); + converter.setFlags(ConverterFlag::Verbose); CORRADE_COMPARE(converter.flags(), ConverterFlag::Verbose); CORRADE_COMPARE(converter._flags, ConverterFlag::Verbose); + + /** @todo use a real flag when we have more than one */ + converter.addFlags(ConverterFlag(4)); + CORRADE_COMPARE(converter.flags(), ConverterFlag::Verbose|ConverterFlag(4)); + CORRADE_COMPARE(converter._flags, ConverterFlag::Verbose|ConverterFlag(4)); + + converter.clearFlags(ConverterFlag::Verbose); + CORRADE_COMPARE(converter.flags(), ConverterFlag(4)); + CORRADE_COMPARE(converter._flags, ConverterFlag(4)); } void AbstractConverterTest::setFlagsBothQuietAndVerbose() { diff --git a/src/Magnum/ShaderTools/shaderconverter.cpp b/src/Magnum/ShaderTools/shaderconverter.cpp index ea4098ef9..bca984b01 100644 --- a/src/Magnum/ShaderTools/shaderconverter.cpp +++ b/src/Magnum/ShaderTools/shaderconverter.cpp @@ -470,7 +470,7 @@ see documentation of a particular converter for more information.)") } } - converter->setFlags(flags); + converter->addFlags(flags); /* If we want just SPIR-V info, convert to a SPIR-V and exit */ if(args.isSet("info")) { diff --git a/src/Magnum/Trade/AbstractImageConverter.cpp b/src/Magnum/Trade/AbstractImageConverter.cpp index 3aea1c9ec..29db56c33 100644 --- a/src/Magnum/Trade/AbstractImageConverter.cpp +++ b/src/Magnum/Trade/AbstractImageConverter.cpp @@ -85,6 +85,14 @@ void AbstractImageConverter::setFlags(ImageConverterFlags flags) { void AbstractImageConverter::doSetFlags(ImageConverterFlags) {} +void AbstractImageConverter::addFlags(ImageConverterFlags flags) { + setFlags(_flags|flags); +} + +void AbstractImageConverter::clearFlags(ImageConverterFlags flags) { + setFlags(_flags & ~flags); +} + Containers::Optional AbstractImageConverter::exportToImage(const ImageView2D& image) { CORRADE_ASSERT(features() & ImageConverterFeature::ConvertImage, "Trade::AbstractImageConverter::exportToImage(): feature not supported", {}); diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index 63ea0f380..92f29855a 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -262,13 +262,35 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract * * Some flags can be set only if the converter supports particular * features, see documentation of each @ref ImageConverterFlag for more - * information. By default no flags are set. + * information. By default no flags are set. To avoid clearing + * potential future default flags by accident, prefer to use + * @ref addFlags() and @ref clearFlags() instead. * * Corresponds to the `-v` / `--verbose` option in * @ref magnum-imageconverter "magnum-imageconverter". */ void setFlags(ImageConverterFlags flags); + /** + * @brief Add converter flags + * @m_since_latest + * + * Calls @ref setFlags() with the existing flags ORed with @p flags. + * Useful for preserving the defaults. + * @see @ref clearFlags() + */ + void addFlags(ImageConverterFlags flags); + + /** + * @brief Clear converter flags + * @m_since_latest + * + * Calls @ref setFlags() with the existing flags ANDed with inverse of + * @p flags. Useful for removing default flags. + * @see @ref addFlags() + */ + void clearFlags(ImageConverterFlags flags); + /** * @brief Convert image to different format * diff --git a/src/Magnum/Trade/AbstractImporter.cpp b/src/Magnum/Trade/AbstractImporter.cpp index 947cbd1bb..7cfc32bb5 100644 --- a/src/Magnum/Trade/AbstractImporter.cpp +++ b/src/Magnum/Trade/AbstractImporter.cpp @@ -104,6 +104,14 @@ void AbstractImporter::setFlags(ImporterFlags flags) { void AbstractImporter::doSetFlags(ImporterFlags) {} +void AbstractImporter::addFlags(ImporterFlags flags) { + setFlags(_flags|flags); +} + +void AbstractImporter::clearFlags(ImporterFlags flags) { + setFlags(_flags & ~flags); +} + void AbstractImporter::setFileCallback(Containers::Optional>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* const userData) { CORRADE_ASSERT(!isOpened(), "Trade::AbstractImporter::setFileCallback(): can't be set while a file is opened", ); CORRADE_ASSERT(features() & (ImporterFeature::FileCallback|ImporterFeature::OpenData), "Trade::AbstractImporter::setFileCallback(): importer supports neither loading from data nor via callbacks, callbacks can't be used", ); diff --git a/src/Magnum/Trade/AbstractImporter.h b/src/Magnum/Trade/AbstractImporter.h index c031a1c95..720c40b3e 100644 --- a/src/Magnum/Trade/AbstractImporter.h +++ b/src/Magnum/Trade/AbstractImporter.h @@ -397,7 +397,9 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi * It's expected that this function is called *before* a file is * opened. Some flags can be set only if the importer supports * particular features, see documentation of each @ref ImporterFlag for - * more information. By default no flags are set. + * more information. By default no flags are set. To avoid clearing + * potential future default flags by accident, prefer to use + * @ref addFlags() and @ref clearFlags() instead. * * Corresponds to the `-v` / `--verbose` option in * @ref magnum-imageconverter "magnum-imageconverter", @@ -406,6 +408,26 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi */ void setFlags(ImporterFlags flags); + /** + * @brief Add importer flags + * @m_since_latest + * + * Calls @ref setFlags() with the existing flags ORed with @p flags. + * Useful for preserving the defaults. + * @see @ref clearFlags() + */ + void addFlags(ImporterFlags flags); + + /** + * @brief Clear importer flags + * @m_since_latest + * + * Calls @ref setFlags() with the existing flags ANDed with inverse of + * @p flags. Useful for removing default flags. + * @see @ref addFlags() + */ + void clearFlags(ImporterFlags flags); + /** * @brief File opening callback function * diff --git a/src/Magnum/Trade/AbstractSceneConverter.cpp b/src/Magnum/Trade/AbstractSceneConverter.cpp index 6c1a6c7de..7807c8d0a 100644 --- a/src/Magnum/Trade/AbstractSceneConverter.cpp +++ b/src/Magnum/Trade/AbstractSceneConverter.cpp @@ -89,6 +89,14 @@ void AbstractSceneConverter::setFlags(SceneConverterFlags flags) { void AbstractSceneConverter::doSetFlags(SceneConverterFlags) {} +void AbstractSceneConverter::addFlags(SceneConverterFlags flags) { + setFlags(_flags|flags); +} + +void AbstractSceneConverter::clearFlags(SceneConverterFlags flags) { + setFlags(_flags & ~flags); +} + Containers::Optional AbstractSceneConverter::convert(const MeshData& mesh) { CORRADE_ASSERT(features() & SceneConverterFeature::ConvertMesh, "Trade::AbstractSceneConverter::convert(): mesh conversion not supported", {}); diff --git a/src/Magnum/Trade/AbstractSceneConverter.h b/src/Magnum/Trade/AbstractSceneConverter.h index e28d0edf9..9b2d7aae3 100644 --- a/src/Magnum/Trade/AbstractSceneConverter.h +++ b/src/Magnum/Trade/AbstractSceneConverter.h @@ -231,13 +231,35 @@ class MAGNUM_TRADE_EXPORT AbstractSceneConverter: public PluginManager::Abstract * * Some flags can be set only if the converter supports particular * features, see documentation of each @ref SceneConverterFlag for more - * information. By default no flags are set. + * information. By default no flags are set. To avoid clearing + * potential future default flags by accident, prefer to use + * @ref addFlags() and @ref clearFlags() instead. * * Corresponds to the `-v` / `--verbose` option in * @ref magnum-sceneconverter "magnum-sceneconverter". */ void setFlags(SceneConverterFlags flags); + /** + * @brief Add converter flags + * @m_since_latest + * + * Calls @ref setFlags() with the existing flags ORed with @p flags. + * Useful for preserving the defaults. + * @see @ref clearFlags() + */ + void addFlags(SceneConverterFlags flags); + + /** + * @brief Clear converter flags + * @m_since_latest + * + * Calls @ref setFlags() with the existing flags ANDed with inverse of + * @p flags. Useful for removing default flags. + * @see @ref addFlags() + */ + void clearFlags(SceneConverterFlags flags); + /** * @brief Convert a mesh * diff --git a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp index a2718951e..d19264257 100644 --- a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp @@ -170,12 +170,21 @@ void AbstractImageConverterTest::setFlags() { ImageConverterFlags _flags; } converter; - CORRADE_COMPARE(converter.flags(), ImageConverterFlags{}); CORRADE_COMPARE(converter._flags, ImageConverterFlags{}); + converter.setFlags(ImageConverterFlag::Verbose); CORRADE_COMPARE(converter.flags(), ImageConverterFlag::Verbose); CORRADE_COMPARE(converter._flags, ImageConverterFlag::Verbose); + + /** @todo use a real flag when we have more than one */ + converter.addFlags(ImageConverterFlag(4)); + CORRADE_COMPARE(converter.flags(), ImageConverterFlag::Verbose|ImageConverterFlag(4)); + CORRADE_COMPARE(converter._flags, ImageConverterFlag::Verbose|ImageConverterFlag(4)); + + converter.clearFlags(ImageConverterFlag::Verbose); + CORRADE_COMPARE(converter.flags(), ImageConverterFlag(4)); + CORRADE_COMPARE(converter._flags, ImageConverterFlag(4)); } void AbstractImageConverterTest::setFlagsNotImplemented() { diff --git a/src/Magnum/Trade/Test/AbstractImporterTest.cpp b/src/Magnum/Trade/Test/AbstractImporterTest.cpp index e535dc95e..6013933e7 100644 --- a/src/Magnum/Trade/Test/AbstractImporterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImporterTest.cpp @@ -540,12 +540,21 @@ void AbstractImporterTest::setFlags() { ImporterFlags _flags; } importer; - CORRADE_COMPARE(importer.flags(), ImporterFlags{}); CORRADE_COMPARE(importer._flags, ImporterFlags{}); + importer.setFlags(ImporterFlag::Verbose); CORRADE_COMPARE(importer.flags(), ImporterFlag::Verbose); CORRADE_COMPARE(importer._flags, ImporterFlag::Verbose); + + /** @todo use a real flag when we have more than one */ + importer.addFlags(ImporterFlag(4)); + CORRADE_COMPARE(importer.flags(), ImporterFlag::Verbose|ImporterFlag(4)); + CORRADE_COMPARE(importer._flags, ImporterFlag::Verbose|ImporterFlag(4)); + + importer.clearFlags(ImporterFlag::Verbose); + CORRADE_COMPARE(importer.flags(), ImporterFlag(4)); + CORRADE_COMPARE(importer._flags, ImporterFlag(4)); } void AbstractImporterTest::setFlagsNotImplemented() { @@ -575,7 +584,13 @@ void AbstractImporterTest::setFlagsFileOpened() { std::ostringstream out; Error redirectError{&out}; importer.setFlags(ImporterFlag::Verbose); - CORRADE_COMPARE(out.str(), "Trade::AbstractImporter::setFlags(): can't be set while a file is opened\n"); + importer.addFlags(ImporterFlag::Verbose); + importer.clearFlags(ImporterFlag::Verbose); + CORRADE_COMPARE(out.str(), + "Trade::AbstractImporter::setFlags(): can't be set while a file is opened\n" + /* These all call into setFlags(), so the same assert is reused */ + "Trade::AbstractImporter::setFlags(): can't be set while a file is opened\n" + "Trade::AbstractImporter::setFlags(): can't be set while a file is opened\n"); } void AbstractImporterTest::openData() { diff --git a/src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp b/src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp index 3fc496116..cbf1baecb 100644 --- a/src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp @@ -142,12 +142,21 @@ void AbstractSceneConverterTest::setFlags() { SceneConverterFlags _flags; } converter; - CORRADE_COMPARE(converter.flags(), SceneConverterFlags{}); CORRADE_COMPARE(converter._flags, SceneConverterFlags{}); + converter.setFlags(SceneConverterFlag::Verbose); CORRADE_COMPARE(converter.flags(), SceneConverterFlag::Verbose); CORRADE_COMPARE(converter._flags, SceneConverterFlag::Verbose); + + /** @todo use a real flag when we have more than one */ + converter.addFlags(SceneConverterFlag(4)); + CORRADE_COMPARE(converter.flags(), SceneConverterFlag::Verbose|SceneConverterFlag(4)); + CORRADE_COMPARE(converter._flags, SceneConverterFlag::Verbose|SceneConverterFlag(4)); + + converter.clearFlags(SceneConverterFlag::Verbose); + CORRADE_COMPARE(converter.flags(), SceneConverterFlag(4)); + CORRADE_COMPARE(converter._flags, SceneConverterFlag(4)); } void AbstractSceneConverterTest::setFlagsNotImplemented() { diff --git a/src/Magnum/Trade/imageconverter.cpp b/src/Magnum/Trade/imageconverter.cpp index 99cd708b5..27dc0001f 100644 --- a/src/Magnum/Trade/imageconverter.cpp +++ b/src/Magnum/Trade/imageconverter.cpp @@ -244,7 +244,7 @@ key=true; configuration subgroups are delimited with /.)") } /* Set options, if passed */ - if(args.isSet("verbose")) importer->setFlags(Trade::ImporterFlag::Verbose); + if(args.isSet("verbose")) importer->addFlags(Trade::ImporterFlag::Verbose); Implementation::setOptions(*importer, args.value("importer-options")); /* Print image info, if requested */ @@ -328,7 +328,7 @@ key=true; configuration subgroups are delimited with /.)") } /* Set options, if passed */ - if(args.isSet("verbose")) converter->setFlags(Trade::ImageConverterFlag::Verbose); + if(args.isSet("verbose")) converter->addFlags(Trade::ImageConverterFlag::Verbose); Implementation::setOptions(*converter, args.value("converter-options")); /* Save output file */ From d636e8f5a397fe381960ba6fef81a56cd2b3bbf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Mar 2021 21:25:45 +0100 Subject: [PATCH 065/161] SceneGraph: pin down the desired destruction order of a tree. This is how it should be but isn't -- the Object inheritance makes it so first the parent pointer is cleared and only then the children get destructed. That doesn't really make sense (and I doubt any code relied on that), so I'll flip it. --- src/Magnum/SceneGraph/Test/ObjectTest.cpp | 98 ++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/Magnum/SceneGraph/Test/ObjectTest.cpp b/src/Magnum/SceneGraph/Test/ObjectTest.cpp index dec800bd4..a2649a79e 100644 --- a/src/Magnum/SceneGraph/Test/ObjectTest.cpp +++ b/src/Magnum/SceneGraph/Test/ObjectTest.cpp @@ -57,6 +57,8 @@ struct ObjectTest: TestSuite::Tester { template void rangeBasedForChildren(); template void rangeBasedForFeatures(); + + void treeDestructionOrder(); }; ObjectTest::ObjectTest() { @@ -96,7 +98,9 @@ ObjectTest::ObjectTest() { &ObjectTest::rangeBasedForChildren, &ObjectTest::rangeBasedForChildren, &ObjectTest::rangeBasedForFeatures, - &ObjectTest::rangeBasedForFeatures}); + &ObjectTest::rangeBasedForFeatures, + + &ObjectTest::treeDestructionOrder}); } template using Object3D = SceneGraph::Object>; @@ -609,6 +613,98 @@ template void ObjectTest::rangeBasedForFeatures() { CORRADE_COMPARE(features, (std::vector*>{&a, &b, &c})); } +void ObjectTest::treeDestructionOrder() { + struct AccessingParent: Object3D { + explicit AccessingParent(Int id, Object3D* parent): Object3D{parent}, id{id} {} + + ~AccessingParent() { + int parentDepth = 0; + Object3D* p = parent(); + while(p) { + ++parentDepth; + p = p->parent(); + } + + Debug{} << "Destructing an object" << id << "with" << parentDepth << "parents and" << (scene() ? "a scene" : "no scene"); + } + + Int id; + }; + + struct AccessingObject: AbstractFeature3D { + explicit AccessingObject(Object3D& object, int id): AbstractFeature3D{object}, id{id} {} + + ~AccessingObject() { + Debug{} << "Destructing a feature" << id << "attached to an object" << static_cast(object()).id; + } + + int id; + }; + + std::stringstream out; + Debug redirectOutput{&out}; + { + struct Scene: Scene3D { + ~Scene() { + Debug{} << "Destructing the scene"; + } + } scene; + + /* These get deleted at the end of scope */ + AccessingParent a{0, &scene}; + AccessingParent b{1, &a}; + AccessingObject bf{b, 0}; + + /* These get deleted as a consequence of b getting out of scope */ + AccessingParent* c = new AccessingParent{2, &b}; + new AccessingObject{*(new AccessingParent{3, c}), 1}; + new AccessingObject{*c, 2}; + + /* These during scene destruction */ + AccessingParent* d = new AccessingParent{4, &scene}; + new AccessingObject{*d, 3}; + + /* These get deleted right now */ + AccessingParent{5, nullptr}; + AccessingObject{b, 4}; + + CORRADE_COMPARE(out.str(), + "Destructing an object 5 with 0 parents and no scene\n" + "Destructing a feature 4 attached to an object 1\n"); + } + + CORRADE_COMPARE(out.str(), + "Destructing an object 5 with 0 parents and no scene\n" + "Destructing a feature 4 attached to an object 1\n" + + /* First a feature that was on stack gets destructed */ + "Destructing a feature 0 attached to an object 1\n" + + /* Then `b`, which then proceeds with destructing heap-allocated child + `c` and its grand child */ + "Destructing an object 1 with 2 parents and a scene\n" + "Destructing an object 2 with 3 parents and a scene\n" + "Destructing an object 3 with 4 parents and a scene\n" + /* and after that the heap-allocated feature attached to the + grandchild */ + "Destructing a feature 1 attached to an object 3\n" + /* and then the feature attached to `c` */ + "Destructing a feature 2 attached to an object 2\n" + + /* Then `a`, which has nothing */ + "Destructing an object 0 with 1 parents and a scene\n" + + /* Then the scene and everything remaining attached to it -- first the + object and then the feature attached to it */ + "Destructing the scene\n" + /* The scene got partially destructed at this point and only an Object + remains of it, which means the isScene() override saying it's a + scene is no longer present */ + "Destructing an object 4 with 1 parents and no scene\n" + "Destructing a feature 3 attached to an object 4\n" + ); +} + }}}} CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::ObjectTest) From ef5a25ee541279fa5f472a3ec5f031ad4bf2d48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Mar 2021 21:57:33 +0100 Subject: [PATCH 066/161] SceneGraph: fix destruction order to preserve parent links. Before the parent link was gone before destructing the children and that just didn't make sense. The test added in previous commit now passes as expected. --- doc/changelog.dox | 12 ++++++++++++ src/Magnum/SceneGraph/Object.h | 7 ++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 9c425ef7b..46bd51182 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -263,6 +263,12 @@ See also: and @ref Platform::EmscriptenApplication::Configuration::clearWindowFlags() for consistency with other application implementations +@subsubsection changelog-latest-changes-shaders SceneGraph library + +- @ref SceneGraph trees are now destructed in a way that preserves + @ref SceneGraph::Object::parent() links up to the root as well as + @ref SceneGraph::AbstractFeature::object() references + @subsubsection changelog-latest-changes-shaders Shaders library - In the original implementation of normal mapping in @ref Shaders::Phong, @@ -524,6 +530,12 @@ See also: afterwards. This can cause compilation breakages in case the type constructor has the parent parameter non-optional, pass the parent explicitly in that case. +- @ref SceneGraph trees are now destructed in a way that preserves + @ref SceneGraph::Object::parent() links up to the root as well as + @ref SceneGraph::AbstractFeature::object() references. Previous behavior + made both @cpp nullptr @ce even before the object/feature destructors were + called and so it's assumed no code relied on such behavior, nevertheless + it's a subtle change worth mentioning. - Due to the rework of @ref Shaders::Phong to support directional and attenuated point lights, the original behavior of unattenuated point lights isn't available anymore. For backwards compatibility, light positions diff --git a/src/Magnum/SceneGraph/Object.h b/src/Magnum/SceneGraph/Object.h index 07f8e1b0f..2437052cf 100644 --- a/src/Magnum/SceneGraph/Object.h +++ b/src/Magnum/SceneGraph/Object.h @@ -104,7 +104,7 @@ class documentation or @ref compilation-speedup-hpp for more information. */ template class Object: public AbstractObject, public Transformation #ifndef DOXYGEN_GENERATING_OUTPUT - , private Containers::LinkedList>, private Containers::LinkedListItem, Object> + , private Containers::LinkedListItem, Object>, private Containers::LinkedList> #endif { public: @@ -126,8 +126,9 @@ template class Object: public AbstractObject Date: Fri, 5 Mar 2021 22:55:05 +0100 Subject: [PATCH 067/161] SceneGraph: clang doesn't seem to "unwind" the vtable on destruction. Interesting. Also yet another proof that relying on ANY OF THIS working in a certain way is a bad, BAD idea. --- src/Magnum/SceneGraph/Test/ObjectTest.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Magnum/SceneGraph/Test/ObjectTest.cpp b/src/Magnum/SceneGraph/Test/ObjectTest.cpp index a2649a79e..6c3160dd1 100644 --- a/src/Magnum/SceneGraph/Test/ObjectTest.cpp +++ b/src/Magnum/SceneGraph/Test/ObjectTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "Magnum/SceneGraph/AbstractFeature.hpp" #include "Magnum/SceneGraph/MatrixTransformation3D.hpp" @@ -673,7 +674,14 @@ void ObjectTest::treeDestructionOrder() { "Destructing a feature 4 attached to an object 1\n"); } - CORRADE_COMPARE(out.str(), + const char* vtableBehavior = + #ifndef CORRADE_TARGET_CLANG + "no scene" + #else + "a scene" /* See below. */ + #endif + ; + CORRADE_COMPARE(out.str(), Utility::formatString( "Destructing an object 5 with 0 parents and no scene\n" "Destructing a feature 4 attached to an object 1\n" @@ -698,11 +706,10 @@ void ObjectTest::treeDestructionOrder() { object and then the feature attached to it */ "Destructing the scene\n" /* The scene got partially destructed at this point and only an Object - remains of it, which means the isScene() override saying it's a - scene is no longer present */ - "Destructing an object 4 with 1 parents and no scene\n" - "Destructing a feature 3 attached to an object 4\n" - ); + may remain of it, which means the isScene() override saying it's a + scene is no longer present. GCC does this but not Clang. */ + "Destructing an object 4 with 1 parents and {}\n" + "Destructing a feature 3 attached to an object 4\n", vtableBehavior)); } }}}} From eb4793719cb47f57ef006d7d56b63427425162e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Mar 2021 20:35:18 +0100 Subject: [PATCH 068/161] doc: put this changelog entry into the correct section. --- doc/changelog.dox | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 46bd51182..973597f72 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -407,6 +407,10 @@ See also: - @cpp Trade::AbstractMaterialData @ce as well as its containing header `Magnum/Trade/AbstractMaterialData.h` is now a deprecated alias to the new and more flexible @ref Trade::MaterialData. +- @cpp Trade::LightData::Type::Infinite @ce, originally adapted from the + OpenGEX specification, is deprecated in favor of + @ref Trade::LightData::Type::Directional as that's the more commonly used + term - @cpp Trade::PhongMaterialData::ambientCoordinateSet() @ce, @cpp diffuseCoordinateSet() @ce, @cpp specularCoordinateSet() @ce and @cpp normalCoordinateSet() @ce are deprecated in favor of more consistently @@ -562,10 +566,6 @@ See also: interfaces, which are also @cpp const @ce and can't fail. Documentation of each function was expanded to suggest a recommended place for potential error handling. -- @cpp Trade::LightData::Type::Infinite @ce, originally adapted from the - OpenGEX specification, is deprecated in favor of - @ref Trade::LightData::Type::Directional as that's the more commonly used - term @subsection changelog-latest-documentation Documentation From 329ccc9db76efcf51cc20ebfd5d0dca40450bf9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Mar 2021 20:36:22 +0100 Subject: [PATCH 069/161] Trade: TextureData constructor was not explicit for some reason. It's a breaking change so it's listed in the changelog, but I don't expect anybody to actually use this constructor implicitly so all fine. --- doc/changelog.dox | 2 ++ src/Magnum/Trade/TextureData.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 973597f72..83e76ba72 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -566,6 +566,8 @@ See also: interfaces, which are also @cpp const @ce and can't fail. Documentation of each function was expanded to suggest a recommended place for potential error handling. +- @ref Trade::TextureData constructor was not @cpp explicit @ce by mistake, + now it is @subsection changelog-latest-documentation Documentation diff --git a/src/Magnum/Trade/TextureData.h b/src/Magnum/Trade/TextureData.h index ed5e55a2f..1bdd2f270 100644 --- a/src/Magnum/Trade/TextureData.h +++ b/src/Magnum/Trade/TextureData.h @@ -64,7 +64,7 @@ class TextureData { * @param image Texture image ID * @param importerState Importer-specific state */ - TextureData(Type type, SamplerFilter minificationFilter, SamplerFilter magnificationFilter, SamplerMipmap mipmapFilter, Array3D wrapping, UnsignedInt image, const void* importerState = nullptr) noexcept: _type{type}, _minificationFilter{minificationFilter}, _magnificationFilter{magnificationFilter}, _mipmapFilter{mipmapFilter}, _wrapping{wrapping}, _image{image}, _importerState{importerState} {} + explicit TextureData(Type type, SamplerFilter minificationFilter, SamplerFilter magnificationFilter, SamplerMipmap mipmapFilter, Array3D wrapping, UnsignedInt image, const void* importerState = nullptr) noexcept: _type{type}, _minificationFilter{minificationFilter}, _magnificationFilter{magnificationFilter}, _mipmapFilter{mipmapFilter}, _wrapping{wrapping}, _image{image}, _importerState{importerState} {} /** @brief Copying is not allowed */ TextureData(const TextureData&) = delete; From 470d22d4cbaec911a9d9d6f5f06dc9c0d175c58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Mar 2021 20:55:50 +0100 Subject: [PATCH 070/161] No need to have explicitly written copy constructors for trivial types. This whole class is gone soon anyway, but this was bothering me. --- src/Magnum/Array.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Magnum/Array.h b/src/Magnum/Array.h index 6c84e9255..1fb2a771c 100644 --- a/src/Magnum/Array.h +++ b/src/Magnum/Array.h @@ -135,9 +135,6 @@ template class Array1D: public Array<1, T> { */ constexpr /*implicit*/ Array1D(T x): Array<1, T>(x) {} - /** @brief Copy constructor */ - constexpr Array1D(const Array<1, T>& other): Array<1, T>(other) {} - T& x() { return Array<1, T>::_data[0]; } /**< @brief X component */ constexpr T x() const { return Array<1, T>::_data[0]; } /**< @overload */ }; @@ -161,9 +158,6 @@ template class Array2D: public Array<2, T> { /** @brief Initializer-list constructor */ constexpr /*implicit*/ Array2D(T value): Array<2, T>(value, value) {} - /** @brief Copy constructor */ - constexpr Array2D(const Array<2, T>& other): Array<2, T>(other) {} - T& x() { return Array<2, T>::_data[0]; } /**< @brief X component */ constexpr T x() const { return Array<2, T>::_data[0]; } /**< @overload */ T& y() { return Array<2, T>::_data[1]; } /**< @brief Y component */ @@ -190,9 +184,6 @@ template class Array3D: public Array<3, T> { /** @brief Initializer-list constructor */ constexpr /*implicit*/ Array3D(T value): Array<3, T>(value, value, value) {} - /** @brief Copy constructor */ - constexpr Array3D(const Array<3, T>& other): Array<3, T>(other) {} - T& x() { return Array<3, T>::_data[0]; } /**< @brief X component */ constexpr T x() const { return Array<3, T>::_data[0]; } /**< @overload */ T& y() { return Array<3, T>::_data[1]; } /**< @brief Y component */ From cc5f2d786279b9b2bf7c0b50baea66bfdf8378ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Mar 2021 20:58:38 +0100 Subject: [PATCH 071/161] Deprecate the weird Magnum::Array class. Its only use was for specifying N-dimensional SamplerWrapping because, compared to a Math::Vector, it had an implicit constructor from a single value (whereas the Vector has it explicit). I solved that by simply adding a few single-value overloads where it mattered. There, done. No need for this weird thing and confusion with Containers::Array anymore. All places that used it now use Math::VectorN, but the class is still included for backwards compatibility purposes, together with providing implicit conversion from and to a Vector. --- doc/changelog.dox | 12 ++++ src/Magnum/Array.h | 68 +++++++++++++++++++---- src/Magnum/CMakeLists.txt | 5 +- src/Magnum/GL/AbstractTexture.cpp | 9 ++- src/Magnum/GL/AbstractTexture.h | 6 +- src/Magnum/GL/CubeMapTexture.h | 26 ++++++++- src/Magnum/GL/CubeMapTextureArray.h | 26 ++++++++- src/Magnum/GL/RectangleTexture.h | 26 ++++++++- src/Magnum/GL/Sampler.h | 11 +++- src/Magnum/GL/Test/SamplerTest.cpp | 8 +-- src/Magnum/GL/Texture.h | 26 ++++++++- src/Magnum/GL/TextureArray.h | 26 ++++++++- src/Magnum/Magnum.h | 14 +++-- src/Magnum/Test/ArrayTest.cpp | 2 + src/Magnum/Test/CMakeLists.txt | 7 ++- src/Magnum/Trade/Test/TextureDataTest.cpp | 6 +- src/Magnum/Trade/TextureData.h | 21 +++++-- src/Magnum/Vk/Enums.h | 12 +++- src/Magnum/Vk/Test/EnumsTest.cpp | 2 +- 19 files changed, 254 insertions(+), 59 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 83e76ba72..e897d255b 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -380,6 +380,18 @@ See also: @subsection changelog-latest-deprecated Deprecated APIs +- The @cpp Array @ce, @cpp Array1D @ce, @cpp Array2D @ce and + @cpp Array3D @ce types that were used exclusively for specifying + @ref SamplerWrapping in various texture APIs are deprecated in favor of + @ref Math::Vector and its subclasses and all existing APIs were switched to + it. The only advantage of this type compared to @ref Math::Vector was that + it provided an implicit constructor from a single value (whereas + @ref Math::Vector has it @cpp explicit @ce), and that's now solved by + simply providing an overload with just a single value where it matters. + It was also commonly confused with @relativeref{Corrade,Containers::Array}, + which is a type with totally different semantics. To avoid breaking + existing code, conversion from and to @ref Math::Vector is now provided and + this type is included in all places where it was originally used. - Markup styling for Emscripten application was switched to prefer using CSS classes instead of the @cb{.css} #container @ce, @cb{.css} #sizer @ce, @cb{.css} #expander @ce, @cb{.css} #listener @ce, @cb{.css} #canvas @ce, diff --git a/src/Magnum/Array.h b/src/Magnum/Array.h index 1fb2a771c..842222af4 100644 --- a/src/Magnum/Array.h +++ b/src/Magnum/Array.h @@ -25,15 +25,26 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file * @brief Class @ref Magnum::Array, @ref Magnum::Array1D, @ref Magnum::Array2D, @ref Magnum::Array3D + * @m_deprecated_since_latest Use @ref Magnum/Math/Vector3.h instead. */ +#endif + +#include "Magnum/configure.h" +#ifdef MAGNUM_BUILD_DEPRECATED #include #include #include +#include #include "Magnum/Magnum.h" +#include "Magnum/Math/Vector3.h" + +/* No CORRADE_DEPRECATED_FILE() as a lot of other headers include this for + implicit conversions */ namespace Magnum { @@ -45,13 +56,12 @@ namespace Implementation { @brief Array @tparam dimensions Dimension count @tparam T Data type +@m_deprecated_since_latest Use @ref Math::Vector instead. -Similar to @ref Math::Vector, but more suitable for storing enum values which -don't need any math operations and fuzzy comparison (e.g. enum values). Unlike -@ref Math::Vector this class has implicit constructor from one value. +Unlike @ref Math::Vector this class has implicit constructor from one value. @see @ref Array1D, @ref Array2D, @ref Array3D */ -template class Array { +template class CORRADE_DEPRECATED("use Math::Vector instead") Array { public: typedef T Type; /**< @brief Data type */ @@ -85,6 +95,12 @@ template class Array { constexpr /*implicit*/ Array(U value): Array(typename Containers::Implementation::GenerateSequence::Type{}, value) {} #endif + /** @brief Convert to a vector */ + /*implicit*/ operator Math::Vector() const { + return Math::Vector::from(_data); + } + + CORRADE_IGNORE_DEPRECATED_PUSH /** @brief Equality */ bool operator==(const Array& other) const { for(UnsignedInt i = 0; i != dimensions; ++i) @@ -96,6 +112,7 @@ template class Array { bool operator!=(const Array& other) const { return !operator==(other); } + CORRADE_IGNORE_DEPRECATED_POP /** @brief Value at given position */ T& operator[](UnsignedInt pos) { return _data[pos]; } @@ -120,11 +137,13 @@ template class Array { template constexpr explicit Array(Containers::Implementation::Sequence, T value): _data{Implementation::repeat(value, sequence)...} {} }; +CORRADE_IGNORE_DEPRECATED_PUSH /** @brief One-dimensional array @tparam T Data type +@m_deprecated_since_latest Use @ref Math::Vector instead. */ -template class Array1D: public Array<1, T> { +template class CORRADE_DEPRECATED("use Math::Vector instead") Array1D: public Array<1, T> { public: /** @copydoc Array::Array() */ constexpr /*implicit*/ Array1D() = default; @@ -135,6 +154,9 @@ template class Array1D: public Array<1, T> { */ constexpr /*implicit*/ Array1D(T x): Array<1, T>(x) {} + /** @brief Construct from a vector */ + constexpr /*implicit*/ Array1D(const Math::Vector<1, T>& vector): Array1D{vector[0]} {} + T& x() { return Array<1, T>::_data[0]; } /**< @brief X component */ constexpr T x() const { return Array<1, T>::_data[0]; } /**< @overload */ }; @@ -142,8 +164,9 @@ template class Array1D: public Array<1, T> { /** @brief Two-dimensional array @tparam T Data type +@m_deprecated_since_latest Use @ref Math::Vector2 instead. */ -template class Array2D: public Array<2, T> { +template class CORRADE_DEPRECATED("use Math::Vector2 instead") Array2D: public Array<2, T> { public: /** @copydoc Array::Array() */ constexpr /*implicit*/ Array2D() = default; @@ -155,6 +178,9 @@ template class Array2D: public Array<2, T> { */ constexpr /*implicit*/ Array2D(T x, T y): Array<2, T>(x, y) {} + /** @brief Construct from a vector */ + constexpr /*implicit*/ Array2D(const Math::Vector2& vector): Array2D{vector.x(), vector.y()} {} + /** @brief Initializer-list constructor */ constexpr /*implicit*/ Array2D(T value): Array<2, T>(value, value) {} @@ -167,8 +193,9 @@ template class Array2D: public Array<2, T> { /** @brief Three-dimensional array @tparam T Data type +@m_deprecated_since_latest Use @ref Math::Vector3 instead. */ -template class Array3D: public Array<3, T> { +template class CORRADE_DEPRECATED("use Math::Vector3 instead") Array3D: public Array<3, T> { public: /** @copydoc Array::Array() */ constexpr /*implicit*/ Array3D() {} @@ -181,6 +208,9 @@ template class Array3D: public Array<3, T> { */ constexpr /*implicit*/ Array3D(T x, T y, T z): Array<3, T>(x, y, z) {} + /** @brief Construct from a vector */ + constexpr /*implicit*/ Array3D(const Math::Vector3& vector): Array3D{vector.x(), vector.y(), vector.z()} {} + /** @brief Initializer-list constructor */ constexpr /*implicit*/ Array3D(T value): Array<3, T>(value, value, value) {} @@ -201,7 +231,10 @@ template class Array3D: public Array<3, T> { } /**< @overload */ }; -/** @debugoperator{Array} */ +/** +@debugoperator{Array} +@m_deprecated_since_latest Use @ref Math::Vector instead. +*/ template Debug& operator<<(Debug& debug, const Array& value) { debug << "Array(" << Debug::nospace; for(UnsignedInt i = 0; i != dimensions; ++i) { @@ -211,21 +244,34 @@ template Debug& operator<<(Debug& debug, const return debug << Debug::nospace << ")"; } -/** @debugoperator{Array1D} */ +/** +@debugoperator{Array1D} +@m_deprecated_since_latest Use @ref Math::Vector instead. +*/ template inline Debug& operator<<(Debug& debug, const Array1D& value) { return debug << static_cast&>(value); } -/** @debugoperator{Array2D} */ +/** +@debugoperator{Array2D} +@m_deprecated_since_latest Use @ref Math::Vector2 instead. +*/ template inline Debug& operator<<(Debug& debug, const Array2D& value) { return debug << static_cast&>(value); } -/** @debugoperator{Array3D} */ +/** +@debugoperator{Array3D} +@m_deprecated_since_latest Use @ref Math::Vector3 instead. +*/ template inline Debug& operator<<(Debug& debug, const Array3D& value) { return debug << static_cast&>(value); } +CORRADE_IGNORE_DEPRECATED_POP } +#else +#error use Magnum/Math/Vector3.h instead +#endif #endif diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 8b3216be0..befc8e7fe 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -75,7 +75,6 @@ set(Magnum_GracefulAssert_SRCS set(Magnum_HEADERS AbstractResourceLoader.h - Array.h British.h DimensionTraits.h FileCallback.h @@ -104,6 +103,10 @@ set(Magnum_PRIVATE_HEADERS Implementation/pixelFormatMapping.hpp Implementation/vertexFormatMapping.hpp) +if(MAGNUM_BUILD_DEPRECATED) + list(APPEND Magnum_HEADERS Array.h) +endif() + # Functionality specific to static Windows builds if(CORRADE_TARGET_WINDOWS AND NOT CORRADE_TARGET_WINDOWS_RT AND MAGNUM_BUILD_STATIC) list(APPEND Magnum_SRCS Implementation/WindowsWeakSymbol.cpp) diff --git a/src/Magnum/GL/AbstractTexture.cpp b/src/Magnum/GL/AbstractTexture.cpp index 4efa513ae..e016256b9 100644 --- a/src/Magnum/GL/AbstractTexture.cpp +++ b/src/Magnum/GL/AbstractTexture.cpp @@ -28,7 +28,6 @@ #include #include -#include "Magnum/Array.h" #include "Magnum/Image.h" #include "Magnum/ImageView.h" #ifndef MAGNUM_TARGET_GLES2 @@ -2354,12 +2353,12 @@ void AbstractTexture::DataHelper<3>::invalidateSubImage(AbstractTexture& texture } #ifndef MAGNUM_TARGET_GLES -void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture& texture, const Array1D& wrapping) { - (texture.*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); +void AbstractTexture::DataHelper<1>::setWrapping(AbstractTexture& texture, const Math::Vector<1, SamplerWrapping>& wrapping) { + (texture.*Context::current().state().texture.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping[0])); } #endif -void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Array2D& wrapping) { +void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const Math::Vector2& wrapping) { const Implementation::TextureState& state = Context::current().state().texture; (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); @@ -2367,7 +2366,7 @@ void AbstractTexture::DataHelper<2>::setWrapping(AbstractTexture& texture, const } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) -void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Array3D& wrapping) { +void AbstractTexture::DataHelper<3>::setWrapping(AbstractTexture& texture, const Math::Vector3& wrapping) { const Implementation::TextureState& state = Context::current().state().texture; (texture.*state.parameteriImplementation)(GL_TEXTURE_WRAP_S, GLint(wrapping.x())); diff --git a/src/Magnum/GL/AbstractTexture.h b/src/Magnum/GL/AbstractTexture.h index 87027a8f2..bcafe5ebe 100644 --- a/src/Magnum/GL/AbstractTexture.h +++ b/src/Magnum/GL/AbstractTexture.h @@ -720,7 +720,7 @@ template<> struct MAGNUM_GL_EXPORT AbstractTexture::DataHelper<1> { static Math::Vector<1, GLint> compressedBlockSize(GLenum target, TextureFormat format); static Math::Vector<1, GLint> imageSize(AbstractTexture& texture, GLint level); - static void setWrapping(AbstractTexture& texture, const Array1D& wrapping); + static void setWrapping(AbstractTexture& texture, const Math::Vector<1, SamplerWrapping>& wrapping); static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Math::Vector<1, GLsizei>& size); @@ -745,7 +745,7 @@ template<> struct MAGNUM_GL_EXPORT AbstractTexture::DataHelper<2> { static Vector2i imageSize(AbstractTexture& texture, GLint level); #endif - static void setWrapping(AbstractTexture& texture, const Array2D& wrapping); + static void setWrapping(AbstractTexture& texture, const Math::Vector2& wrapping); static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Vector2i& size); @@ -790,7 +790,7 @@ template<> struct MAGNUM_GL_EXPORT AbstractTexture::DataHelper<3> { static Vector3i imageSize(AbstractTexture& texture, GLint level); #endif - static void setWrapping(AbstractTexture& texture, const Array3D& wrapping); + static void setWrapping(AbstractTexture& texture, const Math::Vector3& wrapping); static void setStorage(AbstractTexture& texture, GLsizei levels, TextureFormat internalFormat, const Vector3i& size); diff --git a/src/Magnum/GL/CubeMapTexture.h b/src/Magnum/GL/CubeMapTexture.h index f95e751b2..38aec069b 100644 --- a/src/Magnum/GL/CubeMapTexture.h +++ b/src/Magnum/GL/CubeMapTexture.h @@ -29,12 +29,16 @@ * @brief Class @ref Magnum::GL::CubeMapTexture, enum @ref Magnum::GL::CubeMapCoordinate */ -#include "Magnum/Array.h" #include "Magnum/Sampler.h" #include "Magnum/GL/AbstractTexture.h" #include "Magnum/GL/Sampler.h" #include "Magnum/Math/Vector2.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* For implicit conversions to Vector, not used otherwise */ +#include "Magnum/Array.h" +#endif + namespace Magnum { namespace GL { /** @@ -348,16 +352,32 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * * See @ref Texture::setWrapping() for more information. */ - CubeMapTexture& setWrapping(const Array2D& wrapping) { + CubeMapTexture& setWrapping(const Math::Vector2& wrapping) { DataHelper<2>::setWrapping(*this, wrapping); return *this; } /** @overload */ - CubeMapTexture& setWrapping(const Array2D& wrapping) { + CubeMapTexture& setWrapping(const Math::Vector2& wrapping) { return setWrapping(samplerWrapping(wrapping)); } + /** + * @brief Set the same wrapping for all dimensions + * @return Reference to self (for method chaining) + * + * Same as calling @ref setWrapping(const Math::Vector2&) + * with the same value for all dimensions. + */ + CubeMapTexture& setWrapping(SamplerWrapping wrapping) { + return setWrapping(Math::Vector2{wrapping}); + } + + /** @overload */ + CubeMapTexture& setWrapping(Magnum::SamplerWrapping wrapping) { + return setWrapping(Math::Vector2{wrapping}); + } + #ifndef MAGNUM_TARGET_WEBGL /** * @brief @copybrief Texture::setBorderColor(const Color4&) diff --git a/src/Magnum/GL/CubeMapTextureArray.h b/src/Magnum/GL/CubeMapTextureArray.h index ba6045da3..22563848a 100644 --- a/src/Magnum/GL/CubeMapTextureArray.h +++ b/src/Magnum/GL/CubeMapTextureArray.h @@ -31,12 +31,16 @@ */ #endif -#include "Magnum/Array.h" #include "Magnum/Sampler.h" #include "Magnum/GL/AbstractTexture.h" #include "Magnum/GL/Sampler.h" #include "Magnum/Math/Vector3.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* For implicit conversions to Vector, not used otherwise */ +#include "Magnum/Array.h" +#endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) namespace Magnum { namespace GL { @@ -313,16 +317,32 @@ class MAGNUM_GL_EXPORT CubeMapTextureArray: public AbstractTexture { * * See @ref Texture::setWrapping() for more information. */ - CubeMapTextureArray& setWrapping(const Array2D& wrapping) { + CubeMapTextureArray& setWrapping(const Math::Vector2& wrapping) { DataHelper<2>::setWrapping(*this, wrapping); return *this; } /** @overload */ - CubeMapTextureArray& setWrapping(const Array2D& wrapping) { + CubeMapTextureArray& setWrapping(const Math::Vector2& wrapping) { return setWrapping(samplerWrapping(wrapping)); } + /** + * @brief Set the same wrapping for all dimensions + * @return Reference to self (for method chaining) + * + * Same as calling @ref setWrapping(const Math::Vector2&) + * with the same value for all dimensions. + */ + CubeMapTextureArray& setWrapping(SamplerWrapping wrapping) { + return setWrapping(Math::Vector2{wrapping}); + } + + /** @overload */ + CubeMapTextureArray& setWrapping(Magnum::SamplerWrapping wrapping) { + return setWrapping(Math::Vector2{wrapping}); + } + /** * @brief @copybrief Texture::setBorderColor(const Color4&) * @return Reference to self (for method chaining) diff --git a/src/Magnum/GL/RectangleTexture.h b/src/Magnum/GL/RectangleTexture.h index de923e241..719efadf7 100644 --- a/src/Magnum/GL/RectangleTexture.h +++ b/src/Magnum/GL/RectangleTexture.h @@ -31,12 +31,16 @@ */ #endif -#include "Magnum/Array.h" #include "Magnum/Sampler.h" #include "Magnum/GL/AbstractTexture.h" #include "Magnum/GL/Sampler.h" #include "Magnum/Math/Vector2.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* For implicit conversions to Vector, not used otherwise */ +#include "Magnum/Array.h" +#endif + #ifndef MAGNUM_TARGET_GLES namespace Magnum { namespace GL { @@ -214,16 +218,32 @@ class MAGNUM_GL_EXPORT RectangleTexture: public AbstractTexture { * @ref SamplerWrapping::ClampToBorder is supported on this * texture type. */ - RectangleTexture& setWrapping(const Array2D& wrapping) { + RectangleTexture& setWrapping(const Math::Vector2& wrapping) { DataHelper<2>::setWrapping(*this, wrapping); return *this; } /** @overload */ - RectangleTexture& setWrapping(const Array2D& wrapping) { + RectangleTexture& setWrapping(const Math::Vector2& wrapping) { return setWrapping(samplerWrapping(wrapping)); } + /** + * @brief Set the same wrapping for all dimensions + * @return Reference to self (for method chaining) + * + * Same as calling @ref setWrapping(const Math::Vector2&) + * with the same value for all dimensions. + */ + RectangleTexture& setWrapping(SamplerWrapping wrapping) { + return setWrapping(Math::Vector2{wrapping}); + } + + /** @overload */ + RectangleTexture& setWrapping(Magnum::SamplerWrapping wrapping) { + return setWrapping(Math::Vector2{wrapping}); + } + /** * @brief @copybrief Texture::setBorderColor(const Color4&) * @return Reference to self (for method chaining) diff --git a/src/Magnum/GL/Sampler.h b/src/Magnum/GL/Sampler.h index 412b3bdcd..067e85ae9 100644 --- a/src/Magnum/GL/Sampler.h +++ b/src/Magnum/GL/Sampler.h @@ -29,10 +29,15 @@ * @brief Class @ref Magnum::GL::Sampler, enum @ref Magnum::GL::SamplerFilter, @ref Magnum::GL::SamplerMipmap, @ref Magnum::GL::SamplerWrapping, @ref Magnum::GL::SamplerCompareMode, @ref Magnum::GL::SamplerCompareFunction, @ref Magnum::GL::SamplerDepthStencilMode, function @ref Magnum::GL::samplerFilter(), @ref Magnum::GL::samplerMipmap(), @ref Magnum::GL::hasSamplerWrapping(), @ref Magnum::GL::samplerWrapping() */ -#include "Magnum/Array.h" #include "Magnum/Magnum.h" #include "Magnum/GL/OpenGL.h" #include "Magnum/GL/visibility.h" +#include "Magnum/Math/Vector3.h" + +#ifdef MAGNUM_BUILD_DEPRECATED +/* For implicit conversions to Vector, not used otherwise */ +#include "Magnum/Array.h" +#endif namespace Magnum { namespace GL { @@ -201,8 +206,8 @@ function expects that given format is available on the target. Use MAGNUM_GL_EXPORT SamplerWrapping samplerWrapping(Magnum::SamplerWrapping wrapping); /** @overload */ -template Array samplerWrapping(const Array& wrapping) { - Array out; /** @todo NoInit */ +template Math::Vector samplerWrapping(const Math::Vector& wrapping) { + Math::Vector out{NoInit}; for(std::size_t i = 0; i != dimensions; ++i) out[i] = samplerWrapping(wrapping[i]); return out; diff --git a/src/Magnum/GL/Test/SamplerTest.cpp b/src/Magnum/GL/Test/SamplerTest.cpp index c343b3d7f..b2ccaaec3 100644 --- a/src/Magnum/GL/Test/SamplerTest.cpp +++ b/src/Magnum/GL/Test/SamplerTest.cpp @@ -40,7 +40,7 @@ struct SamplerTest: TestSuite::Tester { void mapMipmap(); void mapMipmapInvalid(); void mapWrapping(); - void mapWrappingArray(); + void mapWrappingVector(); void mapWrappingInvalid(); void mapWrappingUnsupported(); @@ -62,7 +62,7 @@ SamplerTest::SamplerTest() { &SamplerTest::mapMipmap, &SamplerTest::mapMipmapInvalid, &SamplerTest::mapWrapping, - &SamplerTest::mapWrappingArray, + &SamplerTest::mapWrappingVector, &SamplerTest::mapWrappingInvalid, &SamplerTest::mapWrappingUnsupported, @@ -137,8 +137,8 @@ void SamplerTest::mapWrapping() { #endif } -void SamplerTest::mapWrappingArray() { - CORRADE_COMPARE(samplerWrapping<2>({Magnum::SamplerWrapping::Repeat, Magnum::SamplerWrapping::ClampToEdge}), (Array2D{SamplerWrapping::Repeat, SamplerWrapping::ClampToEdge})); +void SamplerTest::mapWrappingVector() { + CORRADE_COMPARE(samplerWrapping<2>({Magnum::SamplerWrapping::Repeat, Magnum::SamplerWrapping::ClampToEdge}), (Math::Vector2{SamplerWrapping::Repeat, SamplerWrapping::ClampToEdge})); } void SamplerTest::mapWrappingInvalid() { diff --git a/src/Magnum/GL/Texture.h b/src/Magnum/GL/Texture.h index ddf5f9d45..96f504f4d 100644 --- a/src/Magnum/GL/Texture.h +++ b/src/Magnum/GL/Texture.h @@ -29,13 +29,17 @@ * @brief Class @ref Magnum::GL::Texture, typedef @ref Magnum::GL::Texture1D, @ref Magnum::GL::Texture2D, @ref Magnum::GL::Texture3D */ -#include "Magnum/Array.h" #include "Magnum/Sampler.h" #include "Magnum/DimensionTraits.h" #include "Magnum/GL/AbstractTexture.h" #include "Magnum/GL/Sampler.h" #include "Magnum/Math/Vector3.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* For implicit conversions to Vector, not used otherwise */ +#include "Magnum/Array.h" +#endif + namespace Magnum { namespace GL { namespace Implementation { @@ -468,16 +472,32 @@ template class Texture: public AbstractTexture { * @fn_gl_keyword{TexParameter} with @def_gl_keyword{TEXTURE_WRAP_S}, * @def_gl_keyword{TEXTURE_WRAP_T}, @def_gl_keyword{TEXTURE_WRAP_R} */ - Texture& setWrapping(const Array& wrapping) { + Texture& setWrapping(const Math::Vector& wrapping) { DataHelper::setWrapping(*this, wrapping); return *this; } /** @overload */ - Texture& setWrapping(const Array& wrapping) { + Texture& setWrapping(const Math::Vector& wrapping) { return setWrapping(samplerWrapping(wrapping)); } + /** + * @brief Set the same wrapping for all dimensions + * @return Reference to self (for method chaining) + * + * Same as calling @ref setWrapping(const Math::Vector&) + * with the same value for all dimensions. + */ + Texture& setWrapping(SamplerWrapping wrapping) { + return setWrapping(Math::Vector{wrapping}); + } + + /** @overload */ + Texture& setWrapping(Magnum::SamplerWrapping wrapping) { + return setWrapping(Math::Vector{wrapping}); + } + #ifndef MAGNUM_TARGET_WEBGL /** * @brief Set border color diff --git a/src/Magnum/GL/TextureArray.h b/src/Magnum/GL/TextureArray.h index 7c2837e92..a2da58120 100644 --- a/src/Magnum/GL/TextureArray.h +++ b/src/Magnum/GL/TextureArray.h @@ -31,13 +31,17 @@ */ #endif -#include "Magnum/Array.h" #include "Magnum/Sampler.h" #include "Magnum/DimensionTraits.h" #include "Magnum/GL/AbstractTexture.h" #include "Magnum/GL/Sampler.h" #include "Magnum/Math/Vector3.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* For implicit conversions to Vector, not used otherwise */ +#include "Magnum/Array.h" +#endif + #ifndef MAGNUM_TARGET_GLES2 namespace Magnum { namespace GL { @@ -333,16 +337,32 @@ template class TextureArray: public AbstractTexture { * * See @ref Texture::setWrapping() for more information. */ - TextureArray& setWrapping(const Array& wrapping) { + TextureArray& setWrapping(const Math::Vector& wrapping) { DataHelper::setWrapping(*this, wrapping); return *this; } /** @overload */ - TextureArray& setWrapping(const Array& wrapping) { + TextureArray& setWrapping(const Math::Vector& wrapping) { return setWrapping(samplerWrapping(wrapping)); } + /** + * @brief Set the same wrapping for all dimensions + * @return Reference to self (for method chaining) + * + * Same as calling @ref setWrapping(const Math::Vector&) + * with the same value for all dimensions. + */ + TextureArray& setWrapping(SamplerWrapping wrapping) { + return setWrapping(Math::Vector{wrapping}); + } + + /** @overload */ + TextureArray& setWrapping(Magnum::SamplerWrapping wrapping) { + return setWrapping(Math::Vector{wrapping}); + } + #ifndef MAGNUM_TARGET_WEBGL /** * @brief @copybrief Texture::setBorderColor(const Color4&) diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 310364210..4d68ab0df 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -34,6 +34,10 @@ #include "Magnum/Types.h" #include "Magnum/Math/Math.h" +#ifdef MAGNUM_BUILD_DEPRECATED +#include +#endif + namespace Magnum { /* Bring whole Corrade namespace */ @@ -1129,10 +1133,12 @@ typedef Math::Frustum Frustumd; */ #ifndef DOXYGEN_GENERATING_OUTPUT -template class Array; -template class Array1D; -template class Array2D; -template class Array3D; +#ifdef MAGNUM_BUILD_DEPRECATED +template class CORRADE_DEPRECATED("use Math::Vector instead") Array; +template class CORRADE_DEPRECATED("use Math::Vector instead") Array1D; +template class CORRADE_DEPRECATED("use Math::Vector2 instead") Array2D; +template class CORRADE_DEPRECATED("use Math::Vector3 instead") Array3D; +#endif enum class InputFileCallbackPolicy: UnsignedByte; diff --git a/src/Magnum/Test/ArrayTest.cpp b/src/Magnum/Test/ArrayTest.cpp index 468c97458..38c8fb9e8 100644 --- a/src/Magnum/Test/ArrayTest.cpp +++ b/src/Magnum/Test/ArrayTest.cpp @@ -41,6 +41,7 @@ struct ArrayTest: TestSuite::Tester { void debug(); }; +CORRADE_IGNORE_DEPRECATED_PUSH typedef Magnum::Array1D Array1D; typedef Magnum::Array2D Array2D; typedef Magnum::Array3D Array3D; @@ -121,6 +122,7 @@ void ArrayTest::debug() { Debug{&out} << Array<4, Int>{5, 6, 7, 8} << Array1D{13} << Array2D{71, 2} << Array3D{1, 2, 3}; CORRADE_COMPARE(out.str(), "Array(5, 6, 7, 8) Array(13) Array(71, 2) Array(1, 2, 3)\n"); } +CORRADE_IGNORE_DEPRECATED_POP }}} diff --git a/src/Magnum/Test/CMakeLists.txt b/src/Magnum/Test/CMakeLists.txt index e2a9cc9d4..30ef374f9 100644 --- a/src/Magnum/Test/CMakeLists.txt +++ b/src/Magnum/Test/CMakeLists.txt @@ -23,7 +23,6 @@ # DEALINGS IN THE SOFTWARE. # -corrade_add_test(ArrayTest ArrayTest.cpp LIBRARIES Magnum) corrade_add_test(FileCallbackTest FileCallbackTest.cpp LIBRARIES Magnum) corrade_add_test(ImageTest ImageTest.cpp LIBRARIES MagnumTestLib) corrade_add_test(ImageViewTest ImageViewTest.cpp LIBRARIES MagnumTestLib) @@ -41,7 +40,6 @@ corrade_add_test(MagnumVersionTest VersionTest.cpp LIBRARIES Magnum) corrade_add_test(VertexFormatTest VertexFormatTest.cpp LIBRARIES MagnumTestLib) set_target_properties( - ArrayTest ImageTest ImageViewTest MeshTest @@ -54,6 +52,11 @@ set_target_properties( VertexFormatTest PROPERTIES FOLDER "Magnum/Test") +if(MAGNUM_BUILD_DEPRECATED) + corrade_add_test(ArrayTest ArrayTest.cpp LIBRARIES Magnum) + set_target_properties(ArrayTest PROPERTIES FOLDER "Magnum/Test") +endif() + set_property(TARGET MeshTest PixelFormatTest diff --git a/src/Magnum/Trade/Test/TextureDataTest.cpp b/src/Magnum/Trade/Test/TextureDataTest.cpp index ce0cd1122..5f7d27be7 100644 --- a/src/Magnum/Trade/Test/TextureDataTest.cpp +++ b/src/Magnum/Trade/Test/TextureDataTest.cpp @@ -64,7 +64,7 @@ void TextureDataTest::construct() { CORRADE_COMPARE(data.minificationFilter(), SamplerFilter::Linear); CORRADE_COMPARE(data.magnificationFilter(), SamplerFilter::Nearest); CORRADE_COMPARE(data.mipmapFilter(), SamplerMipmap::Nearest); - CORRADE_COMPARE(data.wrapping(), (Array3D{SamplerWrapping::Repeat, SamplerWrapping::ClampToEdge, SamplerWrapping::MirroredRepeat})); + CORRADE_COMPARE(data.wrapping(), (Math::Vector3{SamplerWrapping::Repeat, SamplerWrapping::ClampToEdge, SamplerWrapping::MirroredRepeat})); CORRADE_COMPARE(data.image(), 42); CORRADE_COMPARE(data.importerState(), &a); } @@ -90,7 +90,7 @@ void TextureDataTest::constructMove() { CORRADE_COMPARE(b.minificationFilter(), SamplerFilter::Linear); CORRADE_COMPARE(b.magnificationFilter(), SamplerFilter::Nearest); CORRADE_COMPARE(b.mipmapFilter(), SamplerMipmap::Nearest); - CORRADE_COMPARE(b.wrapping(), (Array3D{SamplerWrapping::Repeat, SamplerWrapping::ClampToEdge, SamplerWrapping::MirroredRepeat})); + CORRADE_COMPARE(b.wrapping(), (Math::Vector3{SamplerWrapping::Repeat, SamplerWrapping::ClampToEdge, SamplerWrapping::MirroredRepeat})); CORRADE_COMPARE(b.image(), 42); CORRADE_COMPARE(b.importerState(), &a); @@ -108,7 +108,7 @@ void TextureDataTest::constructMove() { CORRADE_COMPARE(d.minificationFilter(), SamplerFilter::Linear); CORRADE_COMPARE(d.magnificationFilter(), SamplerFilter::Nearest); CORRADE_COMPARE(d.mipmapFilter(), SamplerMipmap::Nearest); - CORRADE_COMPARE(d.wrapping(), (Array3D{SamplerWrapping::Repeat, SamplerWrapping::ClampToEdge, SamplerWrapping::MirroredRepeat})); + CORRADE_COMPARE(d.wrapping(), (Math::Vector3{SamplerWrapping::Repeat, SamplerWrapping::ClampToEdge, SamplerWrapping::MirroredRepeat})); CORRADE_COMPARE(d.image(), 42); CORRADE_COMPARE(d.importerState(), &a); diff --git a/src/Magnum/Trade/TextureData.h b/src/Magnum/Trade/TextureData.h index 1bdd2f270..f84109cb9 100644 --- a/src/Magnum/Trade/TextureData.h +++ b/src/Magnum/Trade/TextureData.h @@ -29,10 +29,15 @@ * @brief Class @ref Magnum::Trade::TextureData */ -#include "Magnum/Array.h" #include "Magnum/Sampler.h" +#include "Magnum/Math/Vector3.h" #include "Magnum/Trade/visibility.h" +#ifdef MAGNUM_BUILD_DEPRECATED +/* For implicit conversions to Vector, not used otherwise */ +#include "Magnum/Array.h" +#endif + namespace Magnum { namespace Trade { /** @@ -64,7 +69,15 @@ class TextureData { * @param image Texture image ID * @param importerState Importer-specific state */ - explicit TextureData(Type type, SamplerFilter minificationFilter, SamplerFilter magnificationFilter, SamplerMipmap mipmapFilter, Array3D wrapping, UnsignedInt image, const void* importerState = nullptr) noexcept: _type{type}, _minificationFilter{minificationFilter}, _magnificationFilter{magnificationFilter}, _mipmapFilter{mipmapFilter}, _wrapping{wrapping}, _image{image}, _importerState{importerState} {} + explicit TextureData(Type type, SamplerFilter minificationFilter, SamplerFilter magnificationFilter, SamplerMipmap mipmapFilter, const Math::Vector3& wrapping, UnsignedInt image, const void* importerState = nullptr) noexcept: _type{type}, _minificationFilter{minificationFilter}, _magnificationFilter{magnificationFilter}, _mipmapFilter{mipmapFilter}, _wrapping{wrapping}, _image{image}, _importerState{importerState} {} + + /** + * @brief Construct with the same wrapping for all dimensions + * + * Same as calling @ref TextureData(Type, SamplerFilter, SamplerFilter, SamplerMipmap, const Math::Vector3&, UnsignedInt, const void*) + * with the same @p wrapping value for all dimensions. + */ + explicit TextureData(Type type, SamplerFilter minificationFilter, SamplerFilter magnificationFilter, SamplerMipmap mipmapFilter, SamplerWrapping wrapping, UnsignedInt image, const void* importerState = nullptr) noexcept: _type{type}, _minificationFilter{minificationFilter}, _magnificationFilter{magnificationFilter}, _mipmapFilter{mipmapFilter}, _wrapping{wrapping}, _image{image}, _importerState{importerState} {} /** @brief Copying is not allowed */ TextureData(const TextureData&) = delete; @@ -91,7 +104,7 @@ class TextureData { SamplerMipmap mipmapFilter() const { return _mipmapFilter; } /** @brief Wrapping */ - Array3D wrapping() const { return _wrapping; } + Math::Vector3 wrapping() const { return _wrapping; } /** * @brief Image ID @@ -115,7 +128,7 @@ class TextureData { Type _type; SamplerFilter _minificationFilter, _magnificationFilter; SamplerMipmap _mipmapFilter; - Array3D _wrapping; + Math::Vector3 _wrapping; UnsignedInt _image; const void* _importerState; }; diff --git a/src/Magnum/Vk/Enums.h b/src/Magnum/Vk/Enums.h index 0d67bc260..838f4f084 100644 --- a/src/Magnum/Vk/Enums.h +++ b/src/Magnum/Vk/Enums.h @@ -29,7 +29,8 @@ * @brief Function @ref Magnum::Vk::hasVkPrimitiveTopology(), @ref Magnum::Vk::vkPrimitiveTopology(), @ref Magnum::Vk::hasVkIndexType(), @ref Magnum::Vk::vkIndexType(), @ref Magnum::Vk::hasVkFormat(), @ref Magnum::Vk::vkFormat(), @ref Magnum::Vk::vkFilter(), @ref Magnum::Vk::vkSamplerMipmapMode(), @ref Magnum::Vk::hasVkSamplerAddressMode(), @ref Magnum::Vk::vkSamplerAddressMode() */ -#include "Magnum/Array.h" +#include "Magnum/Magnum.h" +#include "Magnum/Math/Vector3.h" #include "Magnum/Vk/Vulkan.h" #include "Magnum/Vk/visibility.h" @@ -37,6 +38,11 @@ #include #endif +#ifdef MAGNUM_BUILD_DEPRECATED +/* For implicit conversions to Vector, not used otherwise */ +#include "Magnum/Array.h" +#endif + namespace Magnum { namespace Vk { #ifdef MAGNUM_BUILD_DEPRECATED @@ -147,8 +153,8 @@ to query availability of given mode. MAGNUM_VK_EXPORT VkSamplerAddressMode vkSamplerAddressMode(Magnum::SamplerWrapping wrapping); /** @overload */ -template Array vkSamplerAddressMode(const Array& wrapping) { - Array out; /** @todo NoInit */ +template Math::Vector vkSamplerAddressMode(const Math::Vector& wrapping) { + Math::Vector out{NoInit}; for(std::size_t i = 0; i != dimensions; ++i) out[i] = vkSamplerAddressMode(wrapping[i]); return out; diff --git a/src/Magnum/Vk/Test/EnumsTest.cpp b/src/Magnum/Vk/Test/EnumsTest.cpp index a365fbffc..503f11ef6 100644 --- a/src/Magnum/Vk/Test/EnumsTest.cpp +++ b/src/Magnum/Vk/Test/EnumsTest.cpp @@ -115,7 +115,7 @@ void EnumsTest::mapVkSamplerAddressMode() { } void EnumsTest::mapVkSamplerAddressModeArray() { - CORRADE_COMPARE(vkSamplerAddressMode<2>({SamplerWrapping::Repeat, SamplerWrapping::ClampToBorder}), (Array2D{VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER})); + CORRADE_COMPARE(vkSamplerAddressMode<2>({SamplerWrapping::Repeat, SamplerWrapping::ClampToBorder}), (Math::Vector2{VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER})); } void EnumsTest::mapVkSamplerAddressModeUnsupported() { From 1f3361e82e0fd4741e67385c0d7fc83793804146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Mar 2021 21:21:06 +0100 Subject: [PATCH 072/161] doc: oops. --- doc/changelog.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index e897d255b..46984082a 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -263,7 +263,7 @@ See also: and @ref Platform::EmscriptenApplication::Configuration::clearWindowFlags() for consistency with other application implementations -@subsubsection changelog-latest-changes-shaders SceneGraph library +@subsubsection changelog-latest-changes-scenegraph SceneGraph library - @ref SceneGraph trees are now destructed in a way that preserves @ref SceneGraph::Object::parent() links up to the root as well as From d7d4cd72234ee8d107d958944207c6fcc9707787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 7 Mar 2021 22:07:24 +0100 Subject: [PATCH 073/161] Vk: doc++ --- doc/snippets/MagnumVk.cpp | 2 +- doc/vulkan-mapping.dox | 6 ++++-- src/Magnum/Vk/Mesh.h | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index 414ad47f5..9c419c424 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -1032,7 +1032,7 @@ cmd.begin() } { -Vk::Device device{DOXYGEN_IGNORE(NoCreate)}; +Vk::Device device{NoCreate}; /* The include should be a no-op here since it was already included above */ /* [Shader-creation] */ #include diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index 43d5db142..f0000896e 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -64,11 +64,13 @@ Vulkan handle | Matching API @type_vk{DescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{Device} | @ref Device @type_vk{DeviceMemory} | @ref Memory +@type_vk{Event} | | @type_vk{Fence} | @ref Fence @type_vk{Framebuffer} | @ref Framebuffer @type_vk{Image} | @ref Image @type_vk{ImageView} | @ref ImageView @type_vk{Instance} | @ref Instance +@type_vk{PipelineCache} | | @type_vk{PhysicalDevice} | @ref DeviceProperties @type_vk{Pipeline} | @ref Pipeline @type_vk{PipelineLayout} | @ref PipelineLayout @@ -830,7 +832,7 @@ Vulkan enum | Matching API @type_vk{DescriptorUpdateTemplateType} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorType} | | @type_vk{DeviceQueueCreateFlagBits}, \n @type_vk{DeviceQueueCreateFlags} | | -@type_vk{DriverId} @m_class{m-label m-flat m-success} **KHR, 1.2** | | +@type_vk{DriverId} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceDriver @type_vk{DynamicState} | @ref DynamicRasterizationState @subsection vulkan-mapping-enums-e E @@ -968,7 +970,7 @@ Vulkan enum | Matching API @type_vk{SemaphoreWaitFlagBits} @m_class{m-label m-flat m-success} **KHR, 1.2**, \n @type_vk{SemaphoreWaitFlags} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @type_vk{ShaderFloatControlsIndependence} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @type_vk{ShaderGroupShaderKHR} @m_class{m-label m-flat m-warning} **KHR** | | -@type_vk{ShaderModuleCreateFlagBits}, \n @type_vk{ShaderModuleCreateFlags} | @ref ShaderCreateInfo::Flags +@type_vk{ShaderModuleCreateFlagBits}, \n @type_vk{ShaderModuleCreateFlags} | @ref ShaderCreateInfo::Flag, \n @ref ShaderCreateInfo::Flags @type_vk{ShaderStageFlagBits}, \n @type_vk{ShaderStageFlags} | @ref ShaderStage @type_vk{SharingMode} | | @type_vk{SparseImageFormatFlagBits}, \n @type_vk{SparseImageFormatFlags} | | diff --git a/src/Magnum/Vk/Mesh.h b/src/Magnum/Vk/Mesh.h index 2ce1a7829..e1e3a30e9 100644 --- a/src/Magnum/Vk/Mesh.h +++ b/src/Magnum/Vk/Mesh.h @@ -41,6 +41,8 @@ namespace Magnum { namespace Vk { @m_since_latest Wraps a @type_vk_keyword{IndexType}. +@see @ref Magnum::MeshIndexType, @ref meshIndexType(), + @ref Mesh::setIndexBuffer() */ enum class MeshIndexType: Int { /** From 4dace92581654777768a854945957bb1f92ceb1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 9 Mar 2021 11:13:56 +0100 Subject: [PATCH 074/161] Math: add castInto() overloads for Float and Double. --- doc/changelog.dox | 3 +- src/Magnum/Math/PackingBatch.cpp | 8 +++++ src/Magnum/Math/PackingBatch.h | 37 +++++++++++++++++++ src/Magnum/Math/Test/PackingBatchTest.cpp | 43 ++++++++++++++++++++++- 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 46984082a..5fa71864d 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -224,7 +224,8 @@ See also: @subsubsection changelog-latest-changes-math Math library - Added @ref Math::castInto() overloads for casting between @ref UnsignedByte - and @ref UnsignedShort or @ref Byte and @ref Short + and @ref UnsignedShort or @ref Byte and @ref Short, and for casting between + @ref Float and @ref Double @subsubsection changelog-latest-changes-meshtools MeshTools library diff --git a/src/Magnum/Math/PackingBatch.cpp b/src/Magnum/Math/PackingBatch.cpp index e30baeda6..268249fee 100644 --- a/src/Magnum/Math/PackingBatch.cpp +++ b/src/Magnum/Math/PackingBatch.cpp @@ -288,6 +288,14 @@ void castInto(const Corrade::Containers::StridedArrayView2D& src, c castIntoImplementation(src, dst); } +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + castIntoImplementation(src, dst); +} + +void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst) { + castIntoImplementation(src, dst); +} + static_assert(sizeof(HalfMantissaTable) + sizeof(HalfOffsetTable) + sizeof(HalfExponentTable) == 8576, "improper size of half->float conversion tables"); diff --git a/src/Magnum/Math/PackingBatch.h b/src/Magnum/Math/PackingBatch.h index 60d934178..e3359c85d 100644 --- a/src/Magnum/Math/PackingBatch.h +++ b/src/Magnum/Math/PackingBatch.h @@ -348,6 +348,43 @@ MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); +/** +@brief Cast 32-bit floating-point values into a 64-bit floating-point representation +@param[in] src Source float values +@param[out] dst Destination double values +@m_since_latest + +This function performs an equivalent of @cpp Double(a) @ce over the range, so +e.g. @cpp 135.0f @ce becomes @cpp 135.0 @ce. Second dimension is meant to +contain vector/matrix components, or have a size of 1 for scalars. Expects that +@p src and @p dst have the same size and that the second dimension in both is +contiguous. + +@see @ref castInto(const Corrade::Containers::StridedArrayView2D&, const Corrade::Containers::StridedArrayView2D&), + @ref Corrade::Containers::StridedArrayView::isContiguous() +*/ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + +/** +@brief Cast 64-bit floating-point values into a 32-bit floating-point representation +@param[in] src Source double values +@param[out] dst Destination float values +@m_since_latest + +This function performs an equivalent of @cpp Float(a) @ce over the range, so +e.g. @cpp 135.0 @ce becomes @cpp 135.0f @ce. Second dimension is meant to +contain vector/matrix components, or have a size of 1 for scalars. Expects that +@p src and @p dst have the same size and that the second dimension in both is +contiguous. + +@attention Numbers with more than 23 bits of precision will not be represented + accurately when cast into a @ref Magnum::Float "Float". + +@see @ref castInto(const Corrade::Containers::StridedArrayView2D&, const Corrade::Containers::StridedArrayView2D&), + @ref Corrade::Containers::StridedArrayView::isContiguous() +*/ +MAGNUM_EXPORT void castInto(const Corrade::Containers::StridedArrayView2D& src, const Corrade::Containers::StridedArrayView2D& dst); + /* Since 1.8.17, the original short-hand group closing doesn't work anymore. FFS. */ /** diff --git a/src/Magnum/Math/Test/PackingBatchTest.cpp b/src/Magnum/Math/Test/PackingBatchTest.cpp index 42fb9792b..5ac84c475 100644 --- a/src/Magnum/Math/Test/PackingBatchTest.cpp +++ b/src/Magnum/Math/Test/PackingBatchTest.cpp @@ -57,6 +57,8 @@ struct PackingBatchTest: Corrade::TestSuite::Tester { template void castUnsignedInteger(); template void castSignedInteger(); + void castFloatDouble(); + template void assertionsPackUnpack(); void assertionsPackUnpackHalf(); template void assertionsCast(); @@ -89,6 +91,8 @@ PackingBatchTest::PackingBatchTest() { &PackingBatchTest::castSignedInteger, &PackingBatchTest::castSignedInteger, + &PackingBatchTest::castFloatDouble, + &PackingBatchTest::assertionsPackUnpack, &PackingBatchTest::assertionsPackUnpack, &PackingBatchTest::assertionsPackUnpack, @@ -105,7 +109,8 @@ PackingBatchTest::PackingBatchTest() { &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, &PackingBatchTest::assertionsCast, - &PackingBatchTest::assertionsCast}); + &PackingBatchTest::assertionsCast, + &PackingBatchTest::assertionsCast}); } typedef Math::Constants Constants; @@ -573,6 +578,42 @@ template void PackingBatchTest::castSignedInteger() { Corrade::TestSuite::Compare::Container); } +void PackingBatchTest::castFloatDouble() { + struct Data { + Math::Vector2 src; + Math::Vector2 dst; + } data[]{ + {{0.25f, -89.5f}, {}}, + {{-119.0f, 22.75f}, {}}, + {{13.0f, 127.5f}, {}} + }; + + constexpr Math::Vector2 expectedTargetType[] { + {0.25, -89.5}, + {-119.0, 22.75}, + {13.0, 127.5} + }; + + constexpr Math::Vector2 expectedOriginalType[] { + {0.25f, -89.5f}, + {-119.0f, 22.75f}, + {13.0f, 127.5f} + }; + + Corrade::Containers::StridedArrayView1D> src{data, &data[0].src, 3, sizeof(Data)}; + Corrade::Containers::StridedArrayView1D> dst{data, &data[0].dst, 3, sizeof(Data)}; + castInto(Corrade::Containers::arrayCast<2, Float>(src), + Corrade::Containers::arrayCast<2, Double>(dst)); + CORRADE_COMPARE_AS(dst, Corrade::Containers::stridedArrayView(expectedTargetType), + Corrade::TestSuite::Compare::Container); + + /* Test the other way around as well */ + castInto(Corrade::Containers::arrayCast<2, Double>(dst), + Corrade::Containers::arrayCast<2, Float>(src)); + CORRADE_COMPARE_AS(src, Corrade::Containers::stridedArrayView(expectedOriginalType), + Corrade::TestSuite::Compare::Container); +} + template void PackingBatchTest::assertionsPackUnpack() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); From 475b502a1d7b69aa3e513550d6bba9cb128ec04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 8 Mar 2021 13:36:57 +0100 Subject: [PATCH 075/161] package/ci: cap Emscripten jobs. On every CI run, one of these gets aborted due to OOM reasons. Didn't happen before. --- package/ci/circleci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/package/ci/circleci.yml b/package/ci/circleci.yml index 86faeb51d..a07acb662 100644 --- a/package/ci/circleci.yml +++ b/package/ci/circleci.yml @@ -447,6 +447,9 @@ jobs: TARGET_GLES2: "ON" steps: - install-base-linux + # The build is extremely flaky lately (Mar 2021). Not sure why it wasn't a + # problem before. + - cap-ninja-jobs - build: script: emscripten.sh @@ -457,6 +460,9 @@ jobs: TARGET_GLES2: "OFF" steps: - install-base-linux + # The build is extremely flaky lately (Mar 2021). Not sure why it wasn't a + # problem before. + - cap-ninja-jobs - build: script: emscripten.sh From ed9deff432e36f8cca5affd0062eb898bad5c513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 10 Mar 2021 14:45:20 +0100 Subject: [PATCH 076/161] Test: adapt to a less shitty CORRADE_COMPARE(). --- src/Magnum/Animation/Test/TrackViewTest.cpp | 4 +- .../GL/Test/AbstractShaderProgramTest.cpp | 2 +- src/Magnum/GL/Test/AttributeTest.cpp | 30 ++--- src/Magnum/GL/Test/BufferImageTest.cpp | 2 +- src/Magnum/GL/Test/BufferTest.cpp | 2 +- src/Magnum/GL/Test/BufferTextureTest.cpp | 2 +- src/Magnum/GL/Test/ContextTest.cpp | 34 ++--- .../GL/Test/CubeMapTextureArrayTest.cpp | 2 +- src/Magnum/GL/Test/CubeMapTextureTest.cpp | 2 +- src/Magnum/GL/Test/FramebufferTest.cpp | 2 +- src/Magnum/GL/Test/MeshTest.cpp | 4 +- src/Magnum/GL/Test/MultisampleTextureTest.cpp | 4 +- .../GL/Test/PipelineStatisticsQueryTest.cpp | 2 +- src/Magnum/GL/Test/PrimitiveQueryTest.cpp | 2 +- src/Magnum/GL/Test/RectangleTextureTest.cpp | 2 +- src/Magnum/GL/Test/RenderbufferTest.cpp | 2 +- src/Magnum/GL/Test/SampleQueryTest.cpp | 2 +- src/Magnum/GL/Test/ShaderTest.cpp | 2 +- src/Magnum/GL/Test/TextureArrayTest.cpp | 4 +- src/Magnum/GL/Test/TextureTest.cpp | 6 +- src/Magnum/GL/Test/TimeQueryTest.cpp | 2 +- src/Magnum/GL/Test/TransformFeedbackTest.cpp | 2 +- src/Magnum/Math/Test/AngleTest.cpp | 40 +++--- src/Magnum/Math/Test/BezierTest.cpp | 22 ++-- src/Magnum/Math/Test/BoolVectorTest.cpp | 22 ++-- src/Magnum/Math/Test/ColorTest.cpp | 84 ++++++------- src/Magnum/Math/Test/ComplexTest.cpp | 32 ++--- src/Magnum/Math/Test/CubicHermiteTest.cpp | 100 +++++++-------- src/Magnum/Math/Test/DualComplexTest.cpp | 34 ++--- src/Magnum/Math/Test/DualQuaternionTest.cpp | 40 +++--- src/Magnum/Math/Test/DualTest.cpp | 56 ++++----- src/Magnum/Math/Test/FrustumTest.cpp | 16 +-- src/Magnum/Math/Test/FunctionsTest.cpp | 4 +- src/Magnum/Math/Test/HalfTest.cpp | 22 ++-- src/Magnum/Math/Test/Matrix3Test.cpp | 26 ++-- src/Magnum/Math/Test/Matrix4Test.cpp | 26 ++-- src/Magnum/Math/Test/MatrixTest.cpp | 46 +++---- src/Magnum/Math/Test/QuaternionTest.cpp | 30 ++--- src/Magnum/Math/Test/RangeTest.cpp | 66 +++++----- .../Math/Test/RectangularMatrixTest.cpp | 64 +++++----- src/Magnum/Math/Test/TypeTraitsTest.cpp | 28 ++--- src/Magnum/Math/Test/UnitTest.cpp | 18 +-- src/Magnum/Math/Test/Vector2Test.cpp | 24 ++-- src/Magnum/Math/Test/Vector3Test.cpp | 26 ++-- src/Magnum/Math/Test/Vector4Test.cpp | 26 ++-- src/Magnum/Math/Test/VectorTest.cpp | 118 +++++++++--------- src/Magnum/Test/ArrayTest.cpp | 4 +- src/Magnum/Test/ImageViewTest.cpp | 20 +-- src/Magnum/Test/TagsTest.cpp | 6 +- src/Magnum/Vk/Test/BufferTest.cpp | 14 +-- src/Magnum/Vk/Test/CommandBufferTest.cpp | 6 +- src/Magnum/Vk/Test/CommandPoolTest.cpp | 6 +- src/Magnum/Vk/Test/DevicePropertiesTest.cpp | 2 +- src/Magnum/Vk/Test/DeviceTest.cpp | 6 +- src/Magnum/Vk/Test/DeviceVkTest.cpp | 4 +- .../Vk/Test/ExtensionPropertiesTest.cpp | 4 +- src/Magnum/Vk/Test/ExtensionsTest.cpp | 44 +++---- src/Magnum/Vk/Test/FenceTest.cpp | 6 +- src/Magnum/Vk/Test/FramebufferTest.cpp | 10 +- src/Magnum/Vk/Test/ImageTest.cpp | 26 ++-- src/Magnum/Vk/Test/ImageViewTest.cpp | 6 +- src/Magnum/Vk/Test/InstanceTest.cpp | 8 +- src/Magnum/Vk/Test/IntegrationTest.cpp | 4 +- src/Magnum/Vk/Test/LayerPropertiesTest.cpp | 2 +- src/Magnum/Vk/Test/MemoryTest.cpp | 10 +- src/Magnum/Vk/Test/MeshLayoutTest.cpp | 4 +- src/Magnum/Vk/Test/PipelineLayoutTest.cpp | 6 +- src/Magnum/Vk/Test/PipelineTest.cpp | 22 ++-- src/Magnum/Vk/Test/QueueTest.cpp | 10 +- src/Magnum/Vk/Test/RenderPassTest.cpp | 42 +++---- src/Magnum/Vk/Test/ShaderTest.cpp | 10 +- 71 files changed, 684 insertions(+), 684 deletions(-) diff --git a/src/Magnum/Animation/Test/TrackViewTest.cpp b/src/Magnum/Animation/Test/TrackViewTest.cpp index b1277d754..30b98632c 100644 --- a/src/Magnum/Animation/Test/TrackViewTest.cpp +++ b/src/Magnum/Animation/Test/TrackViewTest.cpp @@ -607,8 +607,8 @@ void TrackViewTest::convertToConstView() { CORRADE_COMPARE(ca[1], (std::pair{5.0f, {0.3f, 0.6f, 1.0f}})); /* Conversion back is not possible */ - CORRADE_VERIFY((std::is_convertible, TrackView>::value)); - CORRADE_VERIFY(!(std::is_convertible, TrackView>::value)); + CORRADE_VERIFY(std::is_convertible, TrackView>::value); + CORRADE_VERIFY(!std::is_convertible, TrackView>::value); } const std::pair Keyframes[]{ diff --git a/src/Magnum/GL/Test/AbstractShaderProgramTest.cpp b/src/Magnum/GL/Test/AbstractShaderProgramTest.cpp index db179e611..76a7e0f50 100644 --- a/src/Magnum/GL/Test/AbstractShaderProgramTest.cpp +++ b/src/Magnum/GL/Test/AbstractShaderProgramTest.cpp @@ -51,7 +51,7 @@ void AbstractShaderProgramTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void AbstractShaderProgramTest::constructCopy() { diff --git a/src/Magnum/GL/Test/AttributeTest.cpp b/src/Magnum/GL/Test/AttributeTest.cpp index 31525772f..b236199a6 100644 --- a/src/Magnum/GL/Test/AttributeTest.cpp +++ b/src/Magnum/GL/Test/AttributeTest.cpp @@ -178,7 +178,7 @@ AttributeTest::AttributeTest() { void AttributeTest::attributeScalar() { typedef Attribute<3, Float> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Location, 3); CORRADE_COMPARE(Attribute::Vectors, 1); @@ -214,7 +214,7 @@ void AttributeTest::attributeScalar() { void AttributeTest::attributeScalarInt() { #ifndef MAGNUM_TARGET_GLES2 typedef Attribute<2, Int> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* Default constructor */ @@ -248,7 +248,7 @@ void AttributeTest::attributeScalarInt() { void AttributeTest::attributeScalarUnsignedInt() { #ifndef MAGNUM_TARGET_GLES2 typedef Attribute<3, UnsignedInt> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* Default constructor */ @@ -282,7 +282,7 @@ void AttributeTest::attributeScalarUnsignedInt() { void AttributeTest::attributeScalarDouble() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Double> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* Default constructor */ @@ -303,7 +303,7 @@ void AttributeTest::attributeScalarDouble() { void AttributeTest::attributeVector() { typedef Attribute<3, Vector3> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* Default constructor */ @@ -351,7 +351,7 @@ void AttributeTest::attributeVector() { void AttributeTest::attributeVectorInt() { #ifndef MAGNUM_TARGET_GLES2 typedef Attribute<3, Vector2i> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* Default constructor */ @@ -387,7 +387,7 @@ void AttributeTest::attributeVectorInt() { void AttributeTest::attributeVectorUnsignedInt() { #ifndef MAGNUM_TARGET_GLES2 typedef Attribute<3, Vector4ui> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* Default constructor */ @@ -423,7 +423,7 @@ void AttributeTest::attributeVectorUnsignedInt() { void AttributeTest::attributeVectorDouble() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Vector2d> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* Default constructor */ @@ -458,7 +458,7 @@ void AttributeTest::attributeVectorDouble() { void AttributeTest::attributeVector4() { typedef Attribute<3, Vector4> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* Custom type */ @@ -501,7 +501,7 @@ void AttributeTest::attributeVector4() { void AttributeTest::attributeVectorBGRA() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Vector4> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 1); /* BGRA */ @@ -522,7 +522,7 @@ void AttributeTest::attributeVectorBGRA() { void AttributeTest::attributeMatrixNxN() { typedef Attribute<3, Matrix3> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 3); /* Default constructor */ @@ -542,7 +542,7 @@ void AttributeTest::attributeMatrixNxN() { void AttributeTest::attributeMatrixNxNCustomStride() { typedef Attribute<3, Matrix3> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 3); /* Default stride */ @@ -577,7 +577,7 @@ void AttributeTest::attributeMatrixNxNCustomStride() { #ifndef MAGNUM_TARGET_GLES2 void AttributeTest::attributeMatrixMxN() { typedef Attribute<3, Matrix3x4> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 3); /* Default constructor */ @@ -599,7 +599,7 @@ void AttributeTest::attributeMatrixMxN() { void AttributeTest::attributeMatrixNxNd() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Matrix4d> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 4); /* Default constructor */ @@ -623,7 +623,7 @@ void AttributeTest::attributeMatrixNxNd() { void AttributeTest::attributeMatrixMxNd() { #ifndef MAGNUM_TARGET_GLES typedef Attribute<3, Matrix4x2d> Attribute; - CORRADE_VERIFY((std::is_same{})); + CORRADE_VERIFY(std::is_same{}); CORRADE_COMPARE(Attribute::Vectors, 4); /* Default constructor */ diff --git a/src/Magnum/GL/Test/BufferImageTest.cpp b/src/Magnum/GL/Test/BufferImageTest.cpp index acc15aca2..40f01dd2f 100644 --- a/src/Magnum/GL/Test/BufferImageTest.cpp +++ b/src/Magnum/GL/Test/BufferImageTest.cpp @@ -54,7 +54,7 @@ void BufferImageTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BufferImageTest::constructNoCreateCompressed() { diff --git a/src/Magnum/GL/Test/BufferTest.cpp b/src/Magnum/GL/Test/BufferTest.cpp index 205de7645..498d5f689 100644 --- a/src/Magnum/GL/Test/BufferTest.cpp +++ b/src/Magnum/GL/Test/BufferTest.cpp @@ -62,7 +62,7 @@ void BufferTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BufferTest::constructCopy() { diff --git a/src/Magnum/GL/Test/BufferTextureTest.cpp b/src/Magnum/GL/Test/BufferTextureTest.cpp index a29c71a11..8ceded2a2 100644 --- a/src/Magnum/GL/Test/BufferTextureTest.cpp +++ b/src/Magnum/GL/Test/BufferTextureTest.cpp @@ -48,7 +48,7 @@ void BufferTextureTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BufferTextureTest::constructCopy() { diff --git a/src/Magnum/GL/Test/ContextTest.cpp b/src/Magnum/GL/Test/ContextTest.cpp index 01fb41a4e..afcba1fff 100644 --- a/src/Magnum/GL/Test/ContextTest.cpp +++ b/src/Magnum/GL/Test/ContextTest.cpp @@ -103,39 +103,39 @@ void ContextTest::isExtension() { /* Variadic check (used in variadic Configuration::addDisabledExtensions()), check that it properly fails for each occurence of a non-extension */ #ifndef MAGNUM_TARGET_WEBGL - CORRADE_VERIFY((Implementation::IsExtension< + CORRADE_VERIFY(Implementation::IsExtension< Extensions::KHR::debug, Extensions::EXT::texture_filter_anisotropic, - Extensions::KHR::texture_compression_astc_hdr>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::KHR::texture_compression_astc_hdr>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extension, Extensions::KHR::debug, - Extensions::EXT::texture_filter_anisotropic>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::EXT::texture_filter_anisotropic>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extensions::KHR::debug, Extension, - Extensions::EXT::texture_filter_anisotropic>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::EXT::texture_filter_anisotropic>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extensions::KHR::debug, Extensions::EXT::texture_filter_anisotropic, - Extension>::value)); + Extension>::value); #else - CORRADE_VERIFY((Implementation::IsExtension< + CORRADE_VERIFY(Implementation::IsExtension< Extensions::OES::texture_float_linear, Extensions::EXT::texture_filter_anisotropic, - Extensions::WEBGL::compressed_texture_s3tc>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::WEBGL::compressed_texture_s3tc>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extension, Extensions::OES::texture_float_linear, - Extensions::EXT::texture_filter_anisotropic>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::EXT::texture_filter_anisotropic>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extensions::OES::texture_float_linear, Extension, - Extensions::EXT::texture_filter_anisotropic>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::EXT::texture_filter_anisotropic>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extensions::OES::texture_float_linear, Extensions::EXT::texture_filter_anisotropic, - Extension>::value)); + Extension>::value); #endif /* Empty variadic list should return true */ @@ -350,7 +350,7 @@ void ContextTest::constructNoCreate() { CORRADE_VERIFY(!Context::hasCurrent()); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ContextTest::constructCopy() { diff --git a/src/Magnum/GL/Test/CubeMapTextureArrayTest.cpp b/src/Magnum/GL/Test/CubeMapTextureArrayTest.cpp index 9ef75fb4f..1500a7fa2 100644 --- a/src/Magnum/GL/Test/CubeMapTextureArrayTest.cpp +++ b/src/Magnum/GL/Test/CubeMapTextureArrayTest.cpp @@ -48,7 +48,7 @@ void CubeMapTextureArrayTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubeMapTextureArrayTest::constructCopy() { diff --git a/src/Magnum/GL/Test/CubeMapTextureTest.cpp b/src/Magnum/GL/Test/CubeMapTextureTest.cpp index c908be1c9..50e36faf3 100644 --- a/src/Magnum/GL/Test/CubeMapTextureTest.cpp +++ b/src/Magnum/GL/Test/CubeMapTextureTest.cpp @@ -48,7 +48,7 @@ void CubeMapTextureTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubeMapTextureTest::constructCopy() { diff --git a/src/Magnum/GL/Test/FramebufferTest.cpp b/src/Magnum/GL/Test/FramebufferTest.cpp index 2411e3a37..ed0944d3c 100644 --- a/src/Magnum/GL/Test/FramebufferTest.cpp +++ b/src/Magnum/GL/Test/FramebufferTest.cpp @@ -54,7 +54,7 @@ void FramebufferTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void FramebufferTest::constructCopy() { diff --git a/src/Magnum/GL/Test/MeshTest.cpp b/src/Magnum/GL/Test/MeshTest.cpp index 4b8d43cd4..b2697483d 100644 --- a/src/Magnum/GL/Test/MeshTest.cpp +++ b/src/Magnum/GL/Test/MeshTest.cpp @@ -90,7 +90,7 @@ void MeshTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MeshTest::constructViewNoCreate() { @@ -101,7 +101,7 @@ void MeshTest::constructViewNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MeshTest::constructCopy() { diff --git a/src/Magnum/GL/Test/MultisampleTextureTest.cpp b/src/Magnum/GL/Test/MultisampleTextureTest.cpp index ef4a9e637..c7b83a915 100644 --- a/src/Magnum/GL/Test/MultisampleTextureTest.cpp +++ b/src/Magnum/GL/Test/MultisampleTextureTest.cpp @@ -54,7 +54,7 @@ void MultisampleTextureTest::construct2DNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MultisampleTextureTest::construct2DArrayNoCreate() { @@ -64,7 +64,7 @@ void MultisampleTextureTest::construct2DArrayNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MultisampleTextureTest::constructCopy2D() { diff --git a/src/Magnum/GL/Test/PipelineStatisticsQueryTest.cpp b/src/Magnum/GL/Test/PipelineStatisticsQueryTest.cpp index fb81583d9..b5e4bdbfe 100644 --- a/src/Magnum/GL/Test/PipelineStatisticsQueryTest.cpp +++ b/src/Magnum/GL/Test/PipelineStatisticsQueryTest.cpp @@ -48,7 +48,7 @@ void PipelineStatisticsQueryTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineStatisticsQueryTest::constructCopy() { diff --git a/src/Magnum/GL/Test/PrimitiveQueryTest.cpp b/src/Magnum/GL/Test/PrimitiveQueryTest.cpp index b8049c2bd..daaa85c14 100644 --- a/src/Magnum/GL/Test/PrimitiveQueryTest.cpp +++ b/src/Magnum/GL/Test/PrimitiveQueryTest.cpp @@ -48,7 +48,7 @@ void PrimitiveQueryTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PrimitiveQueryTest::constructCopy() { diff --git a/src/Magnum/GL/Test/RectangleTextureTest.cpp b/src/Magnum/GL/Test/RectangleTextureTest.cpp index 0b2c1d155..3a6177938 100644 --- a/src/Magnum/GL/Test/RectangleTextureTest.cpp +++ b/src/Magnum/GL/Test/RectangleTextureTest.cpp @@ -48,7 +48,7 @@ void RectangleTextureTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RectangleTextureTest::constructCopy() { diff --git a/src/Magnum/GL/Test/RenderbufferTest.cpp b/src/Magnum/GL/Test/RenderbufferTest.cpp index 8ab229101..0a0176d04 100644 --- a/src/Magnum/GL/Test/RenderbufferTest.cpp +++ b/src/Magnum/GL/Test/RenderbufferTest.cpp @@ -48,7 +48,7 @@ void RenderbufferTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RenderbufferTest::constructCopy() { diff --git a/src/Magnum/GL/Test/SampleQueryTest.cpp b/src/Magnum/GL/Test/SampleQueryTest.cpp index 9ec3e1434..a2d0340a7 100644 --- a/src/Magnum/GL/Test/SampleQueryTest.cpp +++ b/src/Magnum/GL/Test/SampleQueryTest.cpp @@ -48,7 +48,7 @@ void SampleQueryTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void SampleQueryTest::constructCopy() { diff --git a/src/Magnum/GL/Test/ShaderTest.cpp b/src/Magnum/GL/Test/ShaderTest.cpp index bcfec7b86..51b78c89c 100644 --- a/src/Magnum/GL/Test/ShaderTest.cpp +++ b/src/Magnum/GL/Test/ShaderTest.cpp @@ -52,7 +52,7 @@ void ShaderTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ShaderTest::constructCopy() { diff --git a/src/Magnum/GL/Test/TextureArrayTest.cpp b/src/Magnum/GL/Test/TextureArrayTest.cpp index b1dc5a31b..6b8473e80 100644 --- a/src/Magnum/GL/Test/TextureArrayTest.cpp +++ b/src/Magnum/GL/Test/TextureArrayTest.cpp @@ -64,7 +64,7 @@ void TextureArrayTest::construct1DNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } #endif @@ -75,7 +75,7 @@ void TextureArrayTest::construct2DNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/GL/Test/TextureTest.cpp b/src/Magnum/GL/Test/TextureTest.cpp index da740ba8a..102f124ba 100644 --- a/src/Magnum/GL/Test/TextureTest.cpp +++ b/src/Magnum/GL/Test/TextureTest.cpp @@ -77,7 +77,7 @@ void TextureTest::construct1DNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } #endif @@ -88,7 +88,7 @@ void TextureTest::construct2DNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } #if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)) @@ -99,7 +99,7 @@ void TextureTest::construct3DNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } #endif diff --git a/src/Magnum/GL/Test/TimeQueryTest.cpp b/src/Magnum/GL/Test/TimeQueryTest.cpp index 616591c2a..d62cb4885 100644 --- a/src/Magnum/GL/Test/TimeQueryTest.cpp +++ b/src/Magnum/GL/Test/TimeQueryTest.cpp @@ -48,7 +48,7 @@ void TimeQueryTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void TimeQueryTest::constructCopy() { diff --git a/src/Magnum/GL/Test/TransformFeedbackTest.cpp b/src/Magnum/GL/Test/TransformFeedbackTest.cpp index d173514cd..b91d40c6b 100644 --- a/src/Magnum/GL/Test/TransformFeedbackTest.cpp +++ b/src/Magnum/GL/Test/TransformFeedbackTest.cpp @@ -48,7 +48,7 @@ void TransformFeedbackTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void TransformFeedbackTest::constructCopy() { diff --git a/src/Magnum/Math/Test/AngleTest.cpp b/src/Magnum/Math/Test/AngleTest.cpp index 3463c7a50..2fce5c065 100644 --- a/src/Magnum/Math/Test/AngleTest.cpp +++ b/src/Magnum/Math/Test/AngleTest.cpp @@ -150,11 +150,11 @@ void AngleTest::construct() { CORRADE_COMPARE(Double(n), 3.14); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void AngleTest::constructDefault() { @@ -169,12 +169,12 @@ void AngleTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void AngleTest::constructNoInit() { @@ -198,12 +198,12 @@ void AngleTest::constructNoInit() { #endif } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void AngleTest::constructConversion() { @@ -216,11 +216,11 @@ void AngleTest::constructConversion() { CORRADE_COMPARE(Double(d), 25.0); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void AngleTest::constructCopy() { @@ -240,17 +240,17 @@ void AngleTest::constructCopy() { void AngleTest::literals() { constexpr auto a = 25.0_deg; - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); CORRADE_COMPARE(Double(a), 25.0); constexpr auto b = 25.0_degf; - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); CORRADE_COMPARE(Float(b), 25.0f); constexpr auto m = 3.14_rad; - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); CORRADE_COMPARE(Double(m), 3.14); constexpr auto n = 3.14_radf; - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); CORRADE_COMPARE(Float(n), 3.14f); } diff --git a/src/Magnum/Math/Test/BezierTest.cpp b/src/Magnum/Math/Test/BezierTest.cpp index 21f74503e..f87346dc8 100644 --- a/src/Magnum/Math/Test/BezierTest.cpp +++ b/src/Magnum/Math/Test/BezierTest.cpp @@ -121,7 +121,7 @@ void BezierTest::construct() { constexpr QuadraticBezier2D a = {Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}}; CORRADE_COMPARE(a, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void BezierTest::constructDefault() { @@ -131,10 +131,10 @@ void BezierTest::constructDefault() { CORRADE_COMPARE(b, (QuadraticBezier2D{Vector2{}, Vector2{}, Vector2{}})); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BezierTest::constructNoInit() { @@ -147,10 +147,10 @@ void BezierTest::constructNoInit() { CORRADE_COMPARE(a, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BezierTest::constructConversion() { @@ -165,9 +165,9 @@ void BezierTest::constructConversion() { CORRADE_COMPARE(b, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void BezierTest::constructFromCubicHermite() { @@ -208,8 +208,8 @@ void BezierTest::convert() { CORRADE_COMPARE(d.y1, a.y1); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void BezierTest::data() { @@ -238,8 +238,8 @@ void BezierTest::data() { } void BezierTest::compare() { - CORRADE_VERIFY((QuadraticBezier2D{Vector2{0.5f, 1.0f + TypeTraits::epsilon()/2}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}} == QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); - CORRADE_VERIFY((QuadraticBezier2D{Vector2{0.5f, 1.1f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.0f + TypeTraits::epsilon()*2}} != QuadraticBezier2D{Vector2{0.5f, 1.1f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.0f}})); + CORRADE_VERIFY(QuadraticBezier2D{Vector2{0.5f, 1.0f + TypeTraits::epsilon()/2}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}} == QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}}); + CORRADE_VERIFY(QuadraticBezier2D{Vector2{0.5f, 1.1f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.0f + TypeTraits::epsilon()*2}} != QuadraticBezier2D{Vector2{0.5f, 1.1f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.0f}}); } void BezierTest::valueLinear() { diff --git a/src/Magnum/Math/Test/BoolVectorTest.cpp b/src/Magnum/Math/Test/BoolVectorTest.cpp index c04d1a5fc..36510bb0a 100644 --- a/src/Magnum/Math/Test/BoolVectorTest.cpp +++ b/src/Magnum/Math/Test/BoolVectorTest.cpp @@ -118,7 +118,7 @@ void BoolVectorTest::construct() { constexpr BoolVector19 a = {0xa5, 0x5f, 0x07}; CORRADE_COMPARE(a, BoolVector19(0xa5, 0x5f, 0x07)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void BoolVectorTest::constructDefault() { @@ -128,10 +128,10 @@ void BoolVectorTest::constructDefault() { CORRADE_COMPARE(b, BoolVector19(0x00, 0x00, 0x00)); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BoolVectorTest::constructNoInit() { @@ -144,10 +144,10 @@ void BoolVectorTest::constructNoInit() { CORRADE_COMPARE(a, BoolVector19(0xa5, 0x5f, 0x07)); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BoolVectorTest::constructOneValue() { @@ -157,9 +157,9 @@ void BoolVectorTest::constructOneValue() { constexpr BoolVector19 b(true); CORRADE_COMPARE(b, BoolVector19(0xff, 0xff, 0x07)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void BoolVectorTest::constructOneElement() { @@ -168,7 +168,7 @@ void BoolVectorTest::constructOneElement() { constexpr BoolVector1 a = 0x01; CORRADE_COMPARE(a, BoolVector1(0x01)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void BoolVectorTest::constructCopy() { @@ -193,8 +193,8 @@ void BoolVectorTest::convert() { CORRADE_COMPARE(d.z, a.z); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible>::value)); - CORRADE_VERIFY(!(std::is_convertible, BVec3>::value)); + CORRADE_VERIFY(!std::is_convertible>::value); + CORRADE_VERIFY(!std::is_convertible, BVec3>::value); } void BoolVectorTest::data() { @@ -266,7 +266,7 @@ void BoolVectorTest::convertBool() { CORRADE_COMPARE(bool(!BoolVector19(0xff, 0xff, 0x04)), false); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BoolVectorTest::all() { diff --git a/src/Magnum/Math/Test/ColorTest.cpp b/src/Magnum/Math/Test/ColorTest.cpp index 0c7352cc5..1f5a74348 100644 --- a/src/Magnum/Math/Test/ColorTest.cpp +++ b/src/Magnum/Math/Test/ColorTest.cpp @@ -295,8 +295,8 @@ void ColorTest::construct() { CORRADE_COMPARE(c, Vector4(1.0f, 0.5f, 0.75f, 1.0f)); CORRADE_COMPARE(d, Math::Vector4(10, 25, 176, 255)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ColorTest::constructDefaultAlphaHalf() { @@ -321,12 +321,12 @@ void ColorTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void ColorTest::constructNoInit() { @@ -342,12 +342,12 @@ void ColorTest::constructNoInit() { CORRADE_COMPARE(b, (Color4{1.0f, 0.5f, 0.75f, 0.5f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void ColorTest::constructOneValue() { @@ -364,11 +364,11 @@ void ColorTest::constructOneValue() { CORRADE_COMPARE(d, Color4ub(67, 67, 67, 255)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ColorTest::constructParts() { @@ -384,7 +384,7 @@ void ColorTest::constructParts() { CORRADE_COMPARE(d, Color4(1.0f, 0.5f, 0.75f, 1.0f)); CORRADE_COMPARE(e, Color4ub(10, 25, 176, 255)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ColorTest::constructConversion() { @@ -397,11 +397,11 @@ void ColorTest::constructConversion() { CORRADE_COMPARE(d, Color4ub(10, 12, 0, 5)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ColorTest::constructPacking() { @@ -466,10 +466,10 @@ void ColorTest::convert() { CORRADE_COMPARE(d4.w, a4.w); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void ColorTest::constructHsv() { @@ -486,7 +486,7 @@ void ColorTest::constructHsv() { CORRADE_COMPARE(saturation, 0.5f); CORRADE_COMPARE(value, 0.9f); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ColorTest::constructHsvDefault() { @@ -501,10 +501,10 @@ void ColorTest::constructHsvDefault() { CORRADE_COMPARE(ca2, (ColorHsv{0.0_degf, 0.0f, 0.0f})); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ColorTest::constructHsvNoInit() { @@ -517,10 +517,10 @@ void ColorTest::constructHsvNoInit() { CORRADE_COMPARE(a, (ColorHsv{135.0_degf, 0.5f, 0.9f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ColorTest::constructHsvConversion() { @@ -537,9 +537,9 @@ void ColorTest::constructHsvConversion() { CORRADE_COMPARE(cb, (ColorHsv(135.0_degf, 0.5f, 0.9f))); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ColorTest::constructHsvCopy() { @@ -556,11 +556,11 @@ void ColorTest::constructHsvCopy() { } void ColorTest::compareHsv() { - CORRADE_VERIFY((ColorHsv{135.0_degf, 0.5f, 0.9f} == ColorHsv{135.0_degf + TypeTraits::epsilon()*100.0_degf, 0.5f, 0.9f})); - CORRADE_VERIFY((ColorHsv{135.0_degf, 0.5f, 0.9f} != ColorHsv{135.0_degf + TypeTraits::epsilon()*400.0_degf, 0.5f, 0.9f})); + CORRADE_VERIFY(ColorHsv{135.0_degf, 0.5f, 0.9f} == ColorHsv{135.0_degf + TypeTraits::epsilon()*100.0_degf, 0.5f, 0.9f}); + CORRADE_VERIFY(ColorHsv{135.0_degf, 0.5f, 0.9f} != ColorHsv{135.0_degf + TypeTraits::epsilon()*400.0_degf, 0.5f, 0.9f}); - CORRADE_VERIFY((ColorHsv{135.0_degf, 0.5f, 0.9f} == ColorHsv{135.0_degf, 0.5f, 0.9f + TypeTraits::epsilon()*0.5f})); - CORRADE_VERIFY((ColorHsv{135.0_degf, 0.5f, 0.9f} != ColorHsv{135.0_degf, 0.5f, 0.9f + TypeTraits::epsilon()*2.0f})); + CORRADE_VERIFY(ColorHsv{135.0_degf, 0.5f, 0.9f} == ColorHsv{135.0_degf, 0.5f, 0.9f + TypeTraits::epsilon()*0.5f}); + CORRADE_VERIFY(ColorHsv{135.0_degf, 0.5f, 0.9f} != ColorHsv{135.0_degf, 0.5f, 0.9f + TypeTraits::epsilon()*2.0f}); } void ColorTest::data() { @@ -582,10 +582,10 @@ void ColorTest::data() { CORRADE_COMPARE(cc3a, (Color3{1.0f, 2.0f, 3.0f})); CORRADE_COMPARE(cc3b, (Color3{1.0f, 2.0f, 3.0f})); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); } void ColorTest::literals() { @@ -1009,16 +1009,16 @@ void ColorTest::swizzleType() { constexpr Color4ub origColor4; constexpr auto a = Math::gather<'y', 'z', 'r'>(origColor3); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); constexpr auto b = Math::gather<'y', 'z', 'a'>(origColor4); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); constexpr auto c = Math::gather<'y', 'z', 'y', 'x'>(origColor3); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); constexpr auto d = Math::gather<'y', 'a', 'y', 'x'>(origColor4); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); } void ColorTest::debug() { diff --git a/src/Magnum/Math/Test/ComplexTest.cpp b/src/Magnum/Math/Test/ComplexTest.cpp index b327306ab..f6fe56efd 100644 --- a/src/Magnum/Math/Test/ComplexTest.cpp +++ b/src/Magnum/Math/Test/ComplexTest.cpp @@ -174,7 +174,7 @@ void ComplexTest::construct() { CORRADE_COMPARE(a.real(), 0.5f); CORRADE_COMPARE(a.imaginary(), -3.7f); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ComplexTest::constructIdentity() { @@ -186,20 +186,20 @@ void ComplexTest::constructIdentity() { CORRADE_COMPARE(b.length(), 1.0f); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ComplexTest::constructZero() { constexpr Complex a{ZeroInit}; CORRADE_COMPARE(a, Complex(0.0f, 0.0f)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ComplexTest::constructNoInit() { @@ -212,10 +212,10 @@ void ComplexTest::constructNoInit() { CORRADE_COMPARE(a, Complex(0.5f, -3.7f)); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ComplexTest::constructFromVector() { @@ -228,10 +228,10 @@ void ComplexTest::constructFromVector() { CORRADE_COMPARE(b, vec); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ComplexTest::constructConversion() { @@ -243,9 +243,9 @@ void ComplexTest::constructConversion() { CORRADE_COMPARE(b, (Complexi{1, 2})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void ComplexTest::constructCopy() { @@ -271,8 +271,8 @@ void ComplexTest::convert() { CORRADE_COMPARE(d.im, a.im); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void ComplexTest::data() { @@ -308,8 +308,8 @@ void ComplexTest::isNormalized() { template void ComplexTest::isNormalizedEpsilon() { setTestCaseTemplateName(TypeTraits::name()); - CORRADE_VERIFY((Math::Complex{T(0.801775644243754) + TypeTraits::epsilon()/T(2.0), T(0.597625146975521)}.isNormalized())); - CORRADE_VERIFY(!(Math::Complex{T(0.801775644243754) + TypeTraits::epsilon()*T(2.0), T(0.597625146975521)}.isNormalized())); + CORRADE_VERIFY(Math::Complex{T(0.801775644243754) + TypeTraits::epsilon()/T(2.0), T(0.597625146975521)}.isNormalized()); + CORRADE_VERIFY(!Math::Complex{T(0.801775644243754) + TypeTraits::epsilon()*T(2.0), T(0.597625146975521)}.isNormalized()); } void ComplexTest::addSubtract() { diff --git a/src/Magnum/Math/Test/CubicHermiteTest.cpp b/src/Magnum/Math/Test/CubicHermiteTest.cpp index 0a7e9b2e9..fa0394f63 100644 --- a/src/Magnum/Math/Test/CubicHermiteTest.cpp +++ b/src/Magnum/Math/Test/CubicHermiteTest.cpp @@ -230,7 +230,7 @@ void CubicHermiteTest::constructScalar() { CORRADE_COMPARE(a.outTangent(), -0.5f); CORRADE_COMPARE(b.outTangent(), -0.5f); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void CubicHermiteTest::constructVector() { @@ -244,7 +244,7 @@ void CubicHermiteTest::constructVector() { CORRADE_COMPARE(a.outTangent(), (Vector2{3.0f, -0.5f})); CORRADE_COMPARE(b.outTangent(), (Vector2{3.0f, -0.5f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void CubicHermiteTest::constructComplex() { @@ -258,7 +258,7 @@ void CubicHermiteTest::constructComplex() { CORRADE_COMPARE(a.outTangent(), (Complex{3.0f, -0.5f})); CORRADE_COMPARE(b.outTangent(), (Complex{3.0f, -0.5f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void CubicHermiteTest::constructQuaternion() { @@ -278,7 +278,7 @@ void CubicHermiteTest::constructQuaternion() { CORRADE_COMPARE(a.outTangent(), (Quaternion{{3.0f, -0.5f, 1.2f}, 0.3f})); CORRADE_COMPARE(b.outTangent(), (Quaternion{{3.0f, -0.5f, 1.2f}, 0.3f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void CubicHermiteTest::constructDefaultScalar() { @@ -289,7 +289,7 @@ void CubicHermiteTest::constructDefaultScalar() { CORRADE_COMPARE(a, (CubicHermite1D{0.0f, 0.0f, 0.0f})); CORRADE_COMPARE(b, (CubicHermite1D{0.0f, 0.0f, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_default_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); } void CubicHermiteTest::constructDefaultVector() { @@ -300,7 +300,7 @@ void CubicHermiteTest::constructDefaultVector() { CORRADE_COMPARE(a, (CubicHermite2D{{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}})); CORRADE_COMPARE(b, (CubicHermite2D{{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}})); - CORRADE_VERIFY((std::is_nothrow_default_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); } void CubicHermiteTest::constructDefaultComplex() { @@ -311,7 +311,7 @@ void CubicHermiteTest::constructDefaultComplex() { CORRADE_COMPARE(a, (CubicHermiteComplex{{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}})); CORRADE_COMPARE(b, (CubicHermiteComplex{{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}})); - CORRADE_VERIFY((std::is_nothrow_default_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); } void CubicHermiteTest::constructDefaultQuaternion() { @@ -328,7 +328,7 @@ void CubicHermiteTest::constructDefaultQuaternion() { {{0.0f, 0.0f, 0.0f}, 1.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f}})); - CORRADE_VERIFY((std::is_nothrow_default_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); } void CubicHermiteTest::constructZeroScalar() { @@ -338,10 +338,10 @@ void CubicHermiteTest::constructZeroScalar() { CORRADE_COMPARE(a, (CubicHermite1D{0.0f, 0.0f, 0.0f})); CORRADE_COMPARE(b, (CubicHermite1D{0.0f, 0.0f, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructZeroVector() { @@ -351,10 +351,10 @@ void CubicHermiteTest::constructZeroVector() { CORRADE_COMPARE(a, (CubicHermite2D{{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}})); CORRADE_COMPARE(b, (CubicHermite2D{{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructZeroComplex() { @@ -364,10 +364,10 @@ void CubicHermiteTest::constructZeroComplex() { CORRADE_COMPARE(a, (CubicHermiteComplex{{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}})); CORRADE_COMPARE(b, (CubicHermiteComplex{{0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructZeroQuaternion() { @@ -383,18 +383,18 @@ void CubicHermiteTest::constructZeroQuaternion() { {{0.0f, 0.0f, 0.0f}, 0.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f}})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructIdentityScalar() { - CORRADE_VERIFY(!(std::is_constructible::value)); + CORRADE_VERIFY(!std::is_constructible::value); } void CubicHermiteTest::constructIdentityVector() { - CORRADE_VERIFY(!(std::is_constructible::value)); + CORRADE_VERIFY(!std::is_constructible::value); } void CubicHermiteTest::constructIdentityComplex() { @@ -404,10 +404,10 @@ void CubicHermiteTest::constructIdentityComplex() { CORRADE_COMPARE(a, (CubicHermiteComplex{{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}})); CORRADE_COMPARE(b, (CubicHermiteComplex{{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructIdentityQuaternion() { @@ -423,10 +423,10 @@ void CubicHermiteTest::constructIdentityQuaternion() { {{0.0f, 0.0f, 0.0f}, 1.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f}})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructNoInitScalar() { @@ -439,10 +439,10 @@ void CubicHermiteTest::constructNoInitScalar() { CORRADE_COMPARE(spline, (CubicHermite1D{2.0f, -2.0f, -0.5f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructNoInitVector() { @@ -455,10 +455,10 @@ void CubicHermiteTest::constructNoInitVector() { CORRADE_COMPARE(spline, (CubicHermite2D{{1.0f, 2.0f}, {1.5f, -2.0f}, {3.0f, -0.5f}})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructNoInitComplex() { @@ -471,10 +471,10 @@ void CubicHermiteTest::constructNoInitComplex() { CORRADE_COMPARE(spline, (CubicHermiteComplex{{1.0f, 2.0f}, {1.5f, -2.0f}, {3.0f, -0.5f}})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructNoInitQuaternion() { @@ -493,10 +493,10 @@ void CubicHermiteTest::constructNoInitQuaternion() { {{3.0f, -0.5f, 1.2f}, 0.3f}})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CubicHermiteTest::constructConversionScalar() { @@ -509,9 +509,9 @@ void CubicHermiteTest::constructConversionScalar() { CORRADE_COMPARE(c, (CubicHermite1Di{2, -2, 0})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void CubicHermiteTest::constructConversionVector() { @@ -524,9 +524,9 @@ void CubicHermiteTest::constructConversionVector() { CORRADE_COMPARE(c, (CubicHermite2Di{{1, 2}, {1, -2}, {3, 0}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void CubicHermiteTest::constructConversionComplex() { @@ -539,9 +539,9 @@ void CubicHermiteTest::constructConversionComplex() { CORRADE_COMPARE(c, (CubicHermiteComplexi{{1, 2}, {1, -2}, {3, 0}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void CubicHermiteTest::constructConversionQuaternion() { @@ -563,9 +563,9 @@ void CubicHermiteTest::constructConversionQuaternion() { {{3, 0, 1}, 0}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void CubicHermiteTest::constructFromBezier() { @@ -723,35 +723,35 @@ void CubicHermiteTest::dataQuaternion() { } void CubicHermiteTest::compareScalar() { - CORRADE_VERIFY((CubicHermite1D{3.0f, 1.0f, 2.0f} == CubicHermite1D{3.0f, 1.0f + TypeTraits::epsilon()/2, 2.0f})); - CORRADE_VERIFY((CubicHermite1D{3.0f, 1.0f, 2.0f} != CubicHermite1D{3.0f + TypeTraits::epsilon()*6, 1.0f, 2.0f})); + CORRADE_VERIFY(CubicHermite1D{3.0f, 1.0f, 2.0f} == CubicHermite1D{3.0f, 1.0f + TypeTraits::epsilon()/2, 2.0f}); + CORRADE_VERIFY(CubicHermite1D{3.0f, 1.0f, 2.0f} != CubicHermite1D{3.0f + TypeTraits::epsilon()*6, 1.0f, 2.0f}); } void CubicHermiteTest::compareVector() { - CORRADE_VERIFY((CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}) == (CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f + TypeTraits::epsilon()/2}})); - CORRADE_VERIFY((CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}) != (CubicHermite2D{{1.0f + TypeTraits::epsilon()*2, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}})); + CORRADE_VERIFY(CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}} == CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f + TypeTraits::epsilon()/2}}); + CORRADE_VERIFY(CubicHermite2D{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}} != CubicHermite2D{{1.0f + TypeTraits::epsilon()*2, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}); } void CubicHermiteTest::compareComplex() { - CORRADE_VERIFY((CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}) == (CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f + TypeTraits::epsilon()/2}})); - CORRADE_VERIFY((CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}) != (CubicHermiteComplex{{1.0f + TypeTraits::epsilon()*2, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}})); + CORRADE_VERIFY(CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}} == CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f + TypeTraits::epsilon()/2}}); + CORRADE_VERIFY(CubicHermiteComplex{{1.0f, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}} != CubicHermiteComplex{{1.0f + TypeTraits::epsilon()*2, 3.0f}, {1.0f, -2.0f}, {3.0f, 2.0f}}); } void CubicHermiteTest::compareQuaternion() { - CORRADE_VERIFY((CubicHermiteQuaternion{ + CORRADE_VERIFY(CubicHermiteQuaternion{ {{1.0f, 3.0f, -1.0f}, 3.0f}, {{1.5f, -2.0f, 0.1f}, 1.0f}, - {{3.0f, -0.5f, 2.0f}, 0.3f}}) == (CubicHermiteQuaternion{ + {{3.0f, -0.5f, 2.0f}, 0.3f}} == CubicHermiteQuaternion{ {{1.0f, 3.0f, -1.0f}, 3.0f}, {{1.5f, -2.0f, 0.1f}, 1.0f + TypeTraits::epsilon()/2}, - {{3.0f, -0.5f, 2.0f}, 0.3f}})); - CORRADE_VERIFY((CubicHermiteQuaternion{ + {{3.0f, -0.5f, 2.0f}, 0.3f}}); + CORRADE_VERIFY(CubicHermiteQuaternion{ {{1.0f, 3.0f, -1.0f}, 3.0f}, {{1.5f, -2.0f, 0.1f}, 1.0f}, - {{3.0f, -0.5f, 2.0f}, 0.3f}}) != (CubicHermiteQuaternion{ + {{3.0f, -0.5f, 2.0f}, 0.3f}} != CubicHermiteQuaternion{ {{1.0f + TypeTraits::epsilon()*2, 3.0f, -1.0f}, 3.0f}, {{1.5f, -2.0f, 0.1f}, 1.0f}, - {{3.0f, -0.5f, 2.0f}, 0.3f}})); + {{3.0f, -0.5f, 2.0f}, 0.3f}}); } void CubicHermiteTest::selectScalar() { diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index 152a176bf..7acf807d5 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -170,7 +170,7 @@ void DualComplexTest::construct() { constexpr DualComplex b(Complex(-1.0f, 2.5f)); CORRADE_COMPARE(b, DualComplex({-1.0f, 2.5f}, {0.0f, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void DualComplexTest::constructIdentity() { @@ -182,20 +182,20 @@ void DualComplexTest::constructIdentity() { CORRADE_COMPARE(b.length(), 1.0f); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DualComplexTest::constructZero() { constexpr DualComplex a{ZeroInit}; CORRADE_COMPARE(a, DualComplex({0.0f, 0.0f}, {0.0f, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DualComplexTest::constructNoInit() { @@ -208,10 +208,10 @@ void DualComplexTest::constructNoInit() { CORRADE_COMPARE(a, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DualComplexTest::constructFromVector() { @@ -219,9 +219,9 @@ void DualComplexTest::constructFromVector() { CORRADE_COMPARE(a, DualComplex({1.0f, 0.0f}, {1.5f, -3.0f})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void DualComplexTest::constructConversion() { @@ -233,9 +233,9 @@ void DualComplexTest::constructConversion() { CORRADE_COMPARE(b, (DualComplexi{{1, 2}, {-15, 7}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void DualComplexTest::constructCopy() { @@ -266,8 +266,8 @@ void DualComplexTest::convert() { CORRADE_COMPARE(d.y, a.y); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void DualComplexTest::data() { @@ -294,16 +294,16 @@ void DualComplexTest::isNormalized() { template void DualComplexTest::isNormalizedEpsilonRotation() { setTestCaseTemplateName(TypeTraits::name()); - CORRADE_VERIFY((Math::DualComplex{{T(0.801775644243754) + TypeTraits::epsilon()/T(2.0), T(0.597625146975521)}, {T(8018055.25501103), T(5975850.58193309)}}.isNormalized())); - CORRADE_VERIFY(!(Math::DualComplex{{T(0.801775644243754) + TypeTraits::epsilon()*T(2.0), T(0.597625146975521)}, {T(8018055.25501103), T(5975850.58193309)}}.isNormalized())); + CORRADE_VERIFY(Math::DualComplex{{T(0.801775644243754) + TypeTraits::epsilon()/T(2.0), T(0.597625146975521)}, {T(8018055.25501103), T(5975850.58193309)}}.isNormalized()); + CORRADE_VERIFY(!Math::DualComplex{{T(0.801775644243754) + TypeTraits::epsilon()*T(2.0), T(0.597625146975521)}, {T(8018055.25501103), T(5975850.58193309)}}.isNormalized()); } template void DualComplexTest::isNormalizedEpsilonTranslation() { setTestCaseTemplateName(TypeTraits::name()); /* Translation does not affect normalization */ - CORRADE_VERIFY((Math::DualComplex{{T(0.801775644243754), T(0.597625146975521)}, {T(8018055.25501103), T(20.5)}}.isNormalized())); - CORRADE_VERIFY((Math::DualComplex{{T(0.801775644243754), T(0.597625146975521)}, {T(8018055.25501103), T(-200000000.0)}}.isNormalized())); + CORRADE_VERIFY(Math::DualComplex{{T(0.801775644243754), T(0.597625146975521)}, {T(8018055.25501103), T(20.5)}}.isNormalized()); + CORRADE_VERIFY(Math::DualComplex{{T(0.801775644243754), T(0.597625146975521)}, {T(8018055.25501103), T(-200000000.0)}}.isNormalized()); } void DualComplexTest::multiply() { diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index df936165c..95c941c5a 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -186,7 +186,7 @@ void DualQuaternionTest::construct() { constexpr DualQuaternion b({{1.0f, 2.0f, 3.0f}, -4.0f}); CORRADE_COMPARE(b, DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void DualQuaternionTest::constructVectorScalar() { @@ -199,7 +199,7 @@ void DualQuaternionTest::constructVectorScalar() { constexpr Quaternion c = a.dual(); CORRADE_COMPARE(c, Quaternion({0.5f, -3.1f, 3.3f}, 2.0f)); - CORRADE_VERIFY((std::is_nothrow_constructible, Math::Dual>::value)); + CORRADE_VERIFY(std::is_nothrow_constructible, Math::Dual>::value); } void DualQuaternionTest::constructIdentity() { @@ -211,20 +211,20 @@ void DualQuaternionTest::constructIdentity() { CORRADE_COMPARE(b.length(), 1.0f); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DualQuaternionTest::constructZero() { constexpr DualQuaternion a{ZeroInit}; CORRADE_COMPARE(a, DualQuaternion({{0.0f, 0.0f, 0.0f}, 0.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DualQuaternionTest::constructNoInit() { @@ -237,10 +237,10 @@ void DualQuaternionTest::constructNoInit() { CORRADE_COMPARE(a, DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DualQuaternionTest::constructFromVector() { @@ -248,9 +248,9 @@ void DualQuaternionTest::constructFromVector() { CORRADE_COMPARE(a, DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{1.0f, 2.0f, 3.0f}, 0.0f})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void DualQuaternionTest::constructConversion() { @@ -262,9 +262,9 @@ void DualQuaternionTest::constructConversion() { CORRADE_COMPARE(b, (DualQuaternioni{{{1, 2, -15}, 7}, {{1, -2, 3}, 0}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void DualQuaternionTest::constructCopy() { @@ -299,8 +299,8 @@ void DualQuaternionTest::convert() { CORRADE_COMPARE(d.du.w, a.du.w); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void DualQuaternionTest::data() { @@ -331,19 +331,19 @@ void DualQuaternionTest::isNormalized() { template void DualQuaternionTest::isNormalizedEpsilonRotation() { setTestCaseTemplateName(TypeTraits::name()); - CORRADE_VERIFY((Math::DualQuaternion{{{T(0.199367934417197) + TypeTraits::epsilon()/T(2.0), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized())); - CORRADE_VERIFY(!(Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083) + TypeTraits::epsilon()*T(2.0)}, {{T(0.440966117079373), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized())); + CORRADE_VERIFY(Math::DualQuaternion{{{T(0.199367934417197) + TypeTraits::epsilon()/T(2.0), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized()); + CORRADE_VERIFY(!Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083) + TypeTraits::epsilon()*T(2.0)}, {{T(0.440966117079373), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized()); } template void DualQuaternionTest::isNormalizedEpsilonTranslation() { setTestCaseTemplateName(TypeTraits::name()); - CORRADE_VERIFY((Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373), T(-0.440120368706115) + TypeTraits::epsilon()*T(2.0), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized())); - CORRADE_VERIFY(!(Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373) + TypeTraits::epsilon()*T(4.0), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized())); + CORRADE_VERIFY(Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373), T(-0.440120368706115) + TypeTraits::epsilon()*T(2.0), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized()); + CORRADE_VERIFY(!Math::DualQuaternion{{{T(0.199367934417197), T(0.0), T(0.0)}, T(0.97992470462083)}, {{T(0.440966117079373) + TypeTraits::epsilon()*T(4.0), T(-0.440120368706115), T(-0.344665143363806)}, T(-0.0897155704877387)}}.isNormalized()); /* Large translation -- large epsilon */ - CORRADE_VERIFY((Math::DualQuaternion{{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128)}, {{T(5056871.9114386), T(-245303.943266211) + TypeTraits::epsilon()*T(10000000.0), T(-606492.066475555)}, T(-6315.26116124973)}}.isNormalized())); - CORRADE_VERIFY(!(Math::DualQuaternion{{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128)}, {{T(5056871.9114386), T(-245303.943266211) + TypeTraits::epsilon()*T(20000000.0), T(-606492.066475555)}, T(-6315.26116124973)}}.isNormalized())); + CORRADE_VERIFY(Math::DualQuaternion{{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128)}, {{T(5056871.9114386), T(-245303.943266211) + TypeTraits::epsilon()*T(10000000.0), T(-606492.066475555)}, T(-6315.26116124973)}}.isNormalized()); + CORRADE_VERIFY(!Math::DualQuaternion{{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128)}, {{T(5056871.9114386), T(-245303.943266211) + TypeTraits::epsilon()*T(20000000.0), T(-606492.066475555)}, T(-6315.26116124973)}}.isNormalized()); } void DualQuaternionTest::lengthSquared() { diff --git a/src/Magnum/Math/Test/DualTest.cpp b/src/Magnum/Math/Test/DualTest.cpp index fb0683b0c..b289c6c6b 100644 --- a/src/Magnum/Math/Test/DualTest.cpp +++ b/src/Magnum/Math/Test/DualTest.cpp @@ -118,7 +118,7 @@ void DualTest::construct() { CORRADE_COMPARE(d.real(), 3.0f); CORRADE_COMPARE(d.dual(), 0.0f); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void DualTest::constructDefault() { @@ -136,12 +136,12 @@ void DualTest::constructZero() { CORRADE_COMPARE(a, Dual(0.0f, 0.0f)); CORRADE_COMPARE(b, Math::Dual>({{0.0f, 0.0f, 0.0f}, 0.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible>, ZeroInitT>::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible>, ZeroInitT>::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible>>::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible>>::value); } void DualTest::constructNoInit() { @@ -157,12 +157,12 @@ void DualTest::constructNoInit() { CORRADE_COMPARE(b, (Math::Dual>{{{3.0f, 0.1f, 1.0f}, 1.0f}, {{0.1f, 0.0f, 1.0f}, 0.3f}})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible>, Magnum::NoInitT>::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible>, Magnum::NoInitT>::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible>>::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible>>::value); } void DualTest::constructConversion() { @@ -174,9 +174,9 @@ void DualTest::constructConversion() { CORRADE_COMPARE(b, (Duali{1, 2})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void DualTest::constructCopy() { @@ -278,8 +278,8 @@ void DualTest::sincos() { void DualTest::sincosWithBase() { /* Verify that the functions can be called with Dual> and Dual> */ - CORRADE_VERIFY((std::is_same{15.0_degf}), Math::Dual>>::value)); - CORRADE_VERIFY((std::is_same{Rad{Constants::pi()/12}}), Math::Dual>>::value)); + CORRADE_VERIFY(std::is_same{15.0_degf}), Math::Dual>>::value); + CORRADE_VERIFY(std::is_same{Rad{Constants::pi()/12}}), Math::Dual>>::value); const auto result = std::make_pair( Dual(0.5f, 0.8660254037844386f*Constants::pi()/2), @@ -317,25 +317,25 @@ typedef BasicDualVec2 DualVec2; void DualTest::subclassTypes() { const DualVec2 a; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); DualVec2 b; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); const Dual c; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); } void DualTest::subclass() { diff --git a/src/Magnum/Math/Test/FrustumTest.cpp b/src/Magnum/Math/Test/FrustumTest.cpp index 6194f4ffb..e22e5ec7d 100644 --- a/src/Magnum/Math/Test/FrustumTest.cpp +++ b/src/Magnum/Math/Test/FrustumTest.cpp @@ -156,7 +156,7 @@ void FrustumTest::construct() { CORRADE_COMPARE(cfar, planes[5]); CORRADE_COMPARE(a.far(), planes[5]); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void FrustumTest::constructIdentity() { @@ -174,10 +174,10 @@ void FrustumTest::constructIdentity() { CORRADE_COMPARE(b, expected); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void FrustumTest::constructNoInit() { @@ -205,7 +205,7 @@ void FrustumTest::constructNoInit() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void FrustumTest::constructConversion() { @@ -228,9 +228,9 @@ void FrustumTest::constructConversion() { CORRADE_COMPARE(b, expected); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void FrustumTest::constructCopy() { @@ -294,8 +294,8 @@ void FrustumTest::convert() { Corrade::TestSuite::Compare::Container); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void FrustumTest::data() { diff --git a/src/Magnum/Math/Test/FunctionsTest.cpp b/src/Magnum/Math/Test/FunctionsTest.cpp index d8b9be6df..b4d67e73e 100644 --- a/src/Magnum/Math/Test/FunctionsTest.cpp +++ b/src/Magnum/Math/Test/FunctionsTest.cpp @@ -588,8 +588,8 @@ void FunctionsTest::trigonometric() { void FunctionsTest::trigonometricWithBase() { /* Verify that the functions can be called with Unit and Unit */ - CORRADE_VERIFY((std::is_same>::value)); - CORRADE_VERIFY((std::is_same>::value)); + CORRADE_VERIFY(std::is_same>::value); + CORRADE_VERIFY(std::is_same>::value); CORRADE_COMPARE(Math::sin(2*15.0_degf), 0.5f); CORRADE_COMPARE(Math::sin(2*Rad(Constants::pi()/12)), 0.5f); diff --git a/src/Magnum/Math/Test/HalfTest.cpp b/src/Magnum/Math/Test/HalfTest.cpp index 8225ed150..ce05e53ce 100644 --- a/src/Magnum/Math/Test/HalfTest.cpp +++ b/src/Magnum/Math/Test/HalfTest.cpp @@ -504,11 +504,11 @@ void HalfTest::constructDefault() { CORRADE_COMPARE(UnsignedShort(b), 0); CORRADE_COMPARE(b.data(), 0); - CORRADE_VERIFY((std::is_nothrow_default_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_default_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void HalfTest::constructValue() { @@ -521,12 +521,12 @@ void HalfTest::constructValue() { CORRADE_COMPARE(a.data(), 0x4300); CORRADE_COMPARE(b.data(), 0x4300); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void HalfTest::constructData() { @@ -534,10 +534,10 @@ void HalfTest::constructData() { CORRADE_COMPARE(Float(a), 3.5f); CORRADE_COMPARE(UnsignedShort(a), 0x4300); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void HalfTest::constructNoInit() { @@ -550,10 +550,10 @@ void HalfTest::constructNoInit() { CORRADE_COMPARE(a, Half{3.5f}); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void HalfTest::constructCopy() { diff --git a/src/Magnum/Math/Test/Matrix3Test.cpp b/src/Magnum/Math/Test/Matrix3Test.cpp index 4e4a196ff..47014d65a 100644 --- a/src/Magnum/Math/Test/Matrix3Test.cpp +++ b/src/Magnum/Math/Test/Matrix3Test.cpp @@ -164,7 +164,7 @@ void Matrix3Test::construct() { {4.5f, 4.0f, 7.0f}, {7.9f, -1.0f, 8.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Matrix3Test::constructIdentity() { @@ -185,10 +185,10 @@ void Matrix3Test::constructIdentity() { CORRADE_COMPARE(identity3, identity3Expected); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Matrix3Test::constructZero() { @@ -197,10 +197,10 @@ void Matrix3Test::constructZero() { {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Matrix3Test::constructNoInit() { @@ -217,10 +217,10 @@ void Matrix3Test::constructNoInit() { {7.9f, -1.0f, 8.0f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Matrix3Test::constructOneValue() { @@ -230,9 +230,9 @@ void Matrix3Test::constructOneValue() { Vector3{1.5f, 1.5f, 1.5f}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Matrix3Test::constructConversion() { @@ -245,9 +245,9 @@ void Matrix3Test::constructConversion() { {7, -1, 8})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Matrix3Test::constructFromDifferentSize() { @@ -304,8 +304,8 @@ void Matrix3Test::convert() { CORRADE_COMPARE(d.a[0], a.a[0]); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void Matrix3Test::isRigidTransformation() { diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index 4a45d200f..63f01d3e3 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -201,7 +201,7 @@ void Matrix4Test::construct() { {1.0f, 2.0f, 3.0f, -1.0f}, {7.9f, -1.0f, 8.0f, -1.5f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Matrix4Test::constructIdentity() { @@ -224,10 +224,10 @@ void Matrix4Test::constructIdentity() { CORRADE_COMPARE(identity3, identity3Expected); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Matrix4Test::constructZero() { @@ -237,10 +237,10 @@ void Matrix4Test::constructZero() { {0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f})); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Matrix4Test::constructNoInit() { @@ -259,10 +259,10 @@ void Matrix4Test::constructNoInit() { {7.9f, -1.0f, 8.0f, -1.5f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Matrix4Test::constructOneValue() { @@ -273,9 +273,9 @@ void Matrix4Test::constructOneValue() { {1.5f, 1.5f, 1.5f, 1.5f}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Matrix4Test::constructConversion() { @@ -290,9 +290,9 @@ void Matrix4Test::constructConversion() { {7, -1, 8, -1})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Matrix4Test::constructFromDifferentSize() { @@ -355,8 +355,8 @@ void Matrix4Test::convert() { CORRADE_COMPARE(d.a[i], a.a[i]); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void Matrix4Test::isRigidTransformation() { diff --git a/src/Magnum/Math/Test/MatrixTest.cpp b/src/Magnum/Math/Test/MatrixTest.cpp index e8169fa26..6964a3655 100644 --- a/src/Magnum/Math/Test/MatrixTest.cpp +++ b/src/Magnum/Math/Test/MatrixTest.cpp @@ -139,7 +139,7 @@ void MatrixTest::construct() { Vector4(1.0f, 2.0f, 3.0f, -1.0f), Vector4(7.9f, -1.0f, 8.0f, -1.5f))); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void MatrixTest::constructIdentity() { @@ -162,10 +162,10 @@ void MatrixTest::constructIdentity() { CORRADE_COMPARE(identity3, identity3Expected); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MatrixTest::constructZero() { @@ -175,10 +175,10 @@ void MatrixTest::constructZero() { Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 0.0f))); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MatrixTest::constructNoInit() { @@ -197,10 +197,10 @@ void MatrixTest::constructNoInit() { Vector4(7.9f, -1.0f, 8.0f, -1.5f))); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MatrixTest::constructOneValue() { @@ -210,9 +210,9 @@ void MatrixTest::constructOneValue() { Vector3{1.5f, 1.5f, 1.5f}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void MatrixTest::constructOneComponent() { @@ -227,7 +227,7 @@ void MatrixTest::constructOneComponent() { constexpr Matrix1x1 c = Vector1{1.5f}; CORRADE_COMPARE(c, Matrix1x1{Vector1{1.5f}}); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void MatrixTest::constructConversion() { @@ -242,9 +242,9 @@ void MatrixTest::constructConversion() { Vector4i(7, -1, 8, -1))); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void MatrixTest::constructFromDifferentSize() { @@ -302,8 +302,8 @@ void MatrixTest::convert() { CORRADE_COMPARE(d.a[i], a.a[i]); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void MatrixTest::isOrthogonal() { @@ -445,19 +445,19 @@ typedef BasicMat2 Mat2; void MatrixTest::subclassTypes() { const Mat2 c; Mat2 a; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); const Mat2 c2; const Vec2 cv; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); } void MatrixTest::subclass() { diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index f93fd1630..b31792c68 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -217,7 +217,7 @@ void QuaternionTest::construct() { CORRADE_COMPARE(a.vector(), Vector3(1.0f, 2.0f, 3.0f)); CORRADE_COMPARE(a.scalar(), -4.0f); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void QuaternionTest::constructIdentity() { @@ -229,20 +229,20 @@ void QuaternionTest::constructIdentity() { CORRADE_COMPARE(b.length(), 1.0f); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void QuaternionTest::constructZero() { constexpr Quaternion a{ZeroInit}; CORRADE_COMPARE(a, Quaternion({0.0f, 0.0f, 0.0f}, 0.0f)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void QuaternionTest::constructNoInit() { @@ -255,10 +255,10 @@ void QuaternionTest::constructNoInit() { CORRADE_COMPARE(a, Quaternion({1.0f, 2.0f, 3.0f}, -4.0f)); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void QuaternionTest::constructFromVector() { @@ -266,9 +266,9 @@ void QuaternionTest::constructFromVector() { CORRADE_COMPARE(a, Quaternion({1.0f, 2.0f, 3.0f}, 0.0f)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void QuaternionTest::constructConversion() { @@ -280,9 +280,9 @@ void QuaternionTest::constructConversion() { CORRADE_COMPARE(b, (Quaternioni{{1, 2, -15}, 7})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void QuaternionTest::constructCopy() { @@ -310,8 +310,8 @@ void QuaternionTest::convert() { CORRADE_COMPARE(d.w, a.w); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void QuaternionTest::data() { @@ -350,8 +350,8 @@ void QuaternionTest::isNormalized() { template void QuaternionTest::isNormalizedEpsilon() { setTestCaseTemplateName(TypeTraits::name()); - CORRADE_VERIFY((Math::Quaternion{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128) + TypeTraits::epsilon()/T(2.0)}.isNormalized())); - CORRADE_VERIFY(!(Math::Quaternion{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128) + TypeTraits::epsilon()*T(2.0)}.isNormalized())); + CORRADE_VERIFY(Math::Quaternion{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128) + TypeTraits::epsilon()/T(2.0)}.isNormalized()); + CORRADE_VERIFY(!Math::Quaternion{{T(0.0106550719778129), T(0.311128101752138), T(-0.0468823167023769)}, T(0.949151106053128) + TypeTraits::epsilon()*T(2.0)}.isNormalized()); } void QuaternionTest::axisAngle() { diff --git a/src/Magnum/Math/Test/RangeTest.cpp b/src/Magnum/Math/Test/RangeTest.cpp index e28a30e0e..d2b81823f 100644 --- a/src/Magnum/Math/Test/RangeTest.cpp +++ b/src/Magnum/Math/Test/RangeTest.cpp @@ -205,9 +205,9 @@ void RangeTest::construct() { CORRADE_COMPARE(b, (Range<2, Int>({3, 5}, {23, 78}))); CORRADE_COMPARE(c, (Range<3, Int>({3, 5, -7}, {23, 78, 2}))); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void RangeTest::constructDefault() { @@ -228,14 +228,14 @@ void RangeTest::constructDefault() { CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void RangeTest::constructNoInit() { @@ -256,14 +256,14 @@ void RangeTest::constructNoInit() { CORRADE_COMPARE(c, (Range3Di{{3, 5, -7}, {23, 78, 2}})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void RangeTest::constructFromSize() { @@ -320,14 +320,14 @@ void RangeTest::constructConversion() { CORRADE_COMPARE(f, Range3Di({1, 2, -1}, {-15, 7, 0})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible, Range<2, Int>>::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible, Range<2, Int>>::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void RangeTest::constructCopy() { @@ -390,14 +390,14 @@ void RangeTest::convert() { CORRADE_COMPARE(m.d, c.d); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible>::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible>::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void RangeTest::access() { @@ -871,12 +871,12 @@ typedef BasicRect Recti; void RangeTest::subclassTypes() { const Vector2i a; - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); const Recti r; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); } void RangeTest::subclass() { diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index 5f5997f74..b91c4fd78 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -157,7 +157,7 @@ void RectangularMatrixTest::construct() { Vector4(5.0f, 6.0f, 7.0f, 8.0f), Vector4(9.0f, 10.0f, 11.0f, 12.0f))); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void RectangularMatrixTest::constructDefault() { @@ -173,10 +173,10 @@ void RectangularMatrixTest::constructDefault() { Vector3(0.0f, 0.0f, 0.0f))); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RectangularMatrixTest::constructNoInit() { @@ -193,10 +193,10 @@ void RectangularMatrixTest::constructNoInit() { Vector4(9.0f, 10.0f, 11.0f, 12.0f))); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RectangularMatrixTest::constructOneValue() { @@ -206,9 +206,9 @@ void RectangularMatrixTest::constructOneValue() { Vector4{1.5f, 1.5f, 1.5f, 1.5f}})); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void RectangularMatrixTest::constructOneComponent() { @@ -223,7 +223,7 @@ void RectangularMatrixTest::constructOneComponent() { constexpr Matrix1x1 c = Vector1{1.5f}; CORRADE_COMPARE(c, Matrix1x1{Vector1{1.5f}}); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void RectangularMatrixTest::constructConversion() { @@ -235,9 +235,9 @@ void RectangularMatrixTest::constructConversion() { Vector2i(-15, 7))); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void RectangularMatrixTest::constructFromData() { @@ -301,8 +301,8 @@ void RectangularMatrixTest::convert() { CORRADE_COMPARE(d.a[i], a.a[i]); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void RectangularMatrixTest::data() { @@ -571,37 +571,37 @@ typedef BasicMat2x2 Mat2x2; void RectangularMatrixTest::subclassTypes() { Float* const data = nullptr; const Float* const cdata = nullptr; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); /* Const operators */ const Mat2x2 c; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same()), Mat2x2>::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same()), Mat2x2>::value); /* Assignment operators */ Mat2x2 a; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); /* Operators on variable-sized matrix */ const BasicMat<3, Float> c2; - CORRADE_VERIFY((std::is_same>::value)); - CORRADE_VERIFY((std::is_same>::value)); - CORRADE_VERIFY((std::is_same()), BasicMat<3, Float>>::value)); + CORRADE_VERIFY(std::is_same>::value); + CORRADE_VERIFY(std::is_same>::value); + CORRADE_VERIFY(std::is_same()), BasicMat<3, Float>>::value); /* Functions */ - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); } void RectangularMatrixTest::subclass() { diff --git a/src/Magnum/Math/Test/TypeTraitsTest.cpp b/src/Magnum/Math/Test/TypeTraitsTest.cpp index d657b5164..e9cab72e9 100644 --- a/src/Magnum/Math/Test/TypeTraitsTest.cpp +++ b/src/Magnum/Math/Test/TypeTraitsTest.cpp @@ -170,7 +170,7 @@ void TypeTraitsTest::isScalar() { CORRADE_VERIFY(IsScalar::value); CORRADE_VERIFY(IsScalar>::value); CORRADE_VERIFY(IsScalar::value); - CORRADE_VERIFY((IsScalar>::value)); + CORRADE_VERIFY(IsScalar>::value); CORRADE_VERIFY(!IsScalar>::value); CORRADE_VERIFY(!IsVector>::value); CORRADE_VERIFY(!IsScalar>::value); @@ -181,7 +181,7 @@ void TypeTraitsTest::isScalar() { void TypeTraitsTest::isVector() { CORRADE_VERIFY(!IsVector::value); CORRADE_VERIFY(!IsVector>::value); - CORRADE_VERIFY((IsVector>>::value)); + CORRADE_VERIFY(IsVector>>::value); CORRADE_VERIFY(IsVector>::value); CORRADE_VERIFY(IsVector>::value); CORRADE_VERIFY(!IsVector>::value); @@ -195,7 +195,7 @@ void TypeTraitsTest::isIntegral() { CORRADE_VERIFY(IsIntegral::value); CORRADE_VERIFY(IsIntegral::value); - CORRADE_VERIFY((IsIntegral>::value)); + CORRADE_VERIFY(IsIntegral>::value); CORRADE_VERIFY(IsIntegral>::value); CORRADE_VERIFY(!IsIntegral::value); CORRADE_VERIFY(!IsIntegral>::value); @@ -205,13 +205,13 @@ void TypeTraitsTest::isIntegral() { void TypeTraitsTest::isFloatingPoint() { CORRADE_VERIFY(!IsFloatingPoint::value); - CORRADE_VERIFY(!(IsFloatingPoint>::value)); + CORRADE_VERIFY(!IsFloatingPoint>::value); CORRADE_VERIFY(IsFloatingPoint::value); - CORRADE_VERIFY((IsFloatingPoint>::value)); + CORRADE_VERIFY(IsFloatingPoint>::value); CORRADE_VERIFY(IsFloatingPoint>::value); CORRADE_VERIFY(IsFloatingPoint>::value); CORRADE_VERIFY(IsFloatingPoint>::value); - CORRADE_VERIFY((IsFloatingPoint>::value)); + CORRADE_VERIFY(IsFloatingPoint>::value); CORRADE_VERIFY(IsFloatingPoint>::value); CORRADE_VERIFY(!IsFloatingPoint::value); } @@ -221,21 +221,21 @@ void TypeTraitsTest::isUnitless() { CORRADE_VERIFY(IsUnitless::value); CORRADE_VERIFY(IsUnitless>::value); CORRADE_VERIFY(!IsUnitless>::value); - CORRADE_VERIFY(!(IsUnitless>::value)); + CORRADE_VERIFY(!IsUnitless>::value); CORRADE_VERIFY(!IsUnitless::value); } void TypeTraitsTest::underlyingTypeOf() { - CORRADE_VERIFY((std::is_same, Int>::value)); + CORRADE_VERIFY(std::is_same, Int>::value); - CORRADE_VERIFY((std::is_same>, Float>::value)); - CORRADE_VERIFY((std::is_same>, Double>::value)); + CORRADE_VERIFY(std::is_same>, Float>::value); + CORRADE_VERIFY(std::is_same>, Double>::value); - CORRADE_VERIFY((std::is_same>, UnsignedByte>::value)); - CORRADE_VERIFY((std::is_same>, Float>::value)); + CORRADE_VERIFY(std::is_same>, UnsignedByte>::value); + CORRADE_VERIFY(std::is_same>, Float>::value); - CORRADE_VERIFY((std::is_same>, Double>::value)); - CORRADE_VERIFY((std::is_same>, Float>::value)); + CORRADE_VERIFY(std::is_same>, Double>::value); + CORRADE_VERIFY(std::is_same>, Float>::value); } template void TypeTraitsTest::epsilonConsistentWithCorrade() { diff --git a/src/Magnum/Math/Test/UnitTest.cpp b/src/Magnum/Math/Test/UnitTest.cpp index 1bf6a2739..d61b5925c 100644 --- a/src/Magnum/Math/Test/UnitTest.cpp +++ b/src/Magnum/Math/Test/UnitTest.cpp @@ -73,10 +73,10 @@ void UnitTest::construct() { CORRADE_COMPARE(Float(a), 25.0f); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void UnitTest::constructDefault() { @@ -86,10 +86,10 @@ void UnitTest::constructDefault() { CORRADE_COMPARE(b, Sec(0.0f)); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void UnitTest::constructNoInit() { @@ -102,10 +102,10 @@ void UnitTest::constructNoInit() { CORRADE_COMPARE(a, Sec{25.0f}); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void UnitTest::constructConversion() { @@ -114,9 +114,9 @@ void UnitTest::constructConversion() { CORRADE_COMPARE(b, Sec(25.0f)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void UnitTest::compare() { diff --git a/src/Magnum/Math/Test/Vector2Test.cpp b/src/Magnum/Math/Test/Vector2Test.cpp index 2a44c495e..1865e16a1 100644 --- a/src/Magnum/Math/Test/Vector2Test.cpp +++ b/src/Magnum/Math/Test/Vector2Test.cpp @@ -107,7 +107,7 @@ void Vector2Test::construct() { constexpr Vector2 a = {1.5f, 2.5f}; CORRADE_COMPARE(a, (Vector<2, Float>(1.5f, 2.5f))); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector2Test::constructDefault() { @@ -117,10 +117,10 @@ void Vector2Test::constructDefault() { CORRADE_COMPARE(b, Vector2(0.0f, 0.0f)); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector2Test::constructNoInit() { @@ -133,10 +133,10 @@ void Vector2Test::constructNoInit() { CORRADE_COMPARE(a, (Vector2{1.5f, 2.5f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector2Test::constructOneValue() { @@ -144,9 +144,9 @@ void Vector2Test::constructOneValue() { CORRADE_COMPARE(a, Vector2(3.0f, 3.0f)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector2Test::constructConversion() { @@ -155,9 +155,9 @@ void Vector2Test::constructConversion() { CORRADE_COMPARE(b, Vector2i(1, 2)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector2Test::constructCopy() { @@ -184,8 +184,8 @@ void Vector2Test::convert() { CORRADE_COMPARE(d.y, a.y); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector2Test::access() { @@ -252,7 +252,7 @@ void Vector2Test::strictWeakOrdering() { void Vector2Test::swizzleType() { constexpr Vector<4, Int> orig; constexpr auto a = gather<'y', 'a'>(orig); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); } void Vector2Test::debug() { diff --git a/src/Magnum/Math/Test/Vector3Test.cpp b/src/Magnum/Math/Test/Vector3Test.cpp index 911ec82cf..51fd057b8 100644 --- a/src/Magnum/Math/Test/Vector3Test.cpp +++ b/src/Magnum/Math/Test/Vector3Test.cpp @@ -107,7 +107,7 @@ void Vector3Test::construct() { constexpr Vector3 a = {1.0f, 2.5f, -3.0f}; CORRADE_COMPARE(a, (Vector<3, Float>(1.0f, 2.5f, -3.0f))); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector3Test::constructDefault() { @@ -117,10 +117,10 @@ void Vector3Test::constructDefault() { CORRADE_COMPARE(b, Vector3(0.0f, 0.0f, 0.0f)); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector3Test::constructNoInit() { @@ -133,10 +133,10 @@ void Vector3Test::constructNoInit() { CORRADE_COMPARE(a, (Vector3{1.0f, 2.5f, -3.0f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector3Test::constructOneValue() { @@ -144,9 +144,9 @@ void Vector3Test::constructOneValue() { CORRADE_COMPARE(a, Vector3(-3.0f, -3.0f, -3.0f)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector3Test::constructParts() { @@ -154,7 +154,7 @@ void Vector3Test::constructParts() { constexpr Vector3 b = {a, 3.0f}; CORRADE_COMPARE(b, Vector3(1.0f, 2.0f, 3.0f)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector3Test::constructConversion() { @@ -163,9 +163,9 @@ void Vector3Test::constructConversion() { CORRADE_COMPARE(b, Vector3i(1, 2, -3)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector3Test::constructCopy() { @@ -193,8 +193,8 @@ void Vector3Test::convert() { CORRADE_COMPARE(d.z, a.z); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector3Test::access() { @@ -276,7 +276,7 @@ void Vector3Test::strictWeakOrdering() { void Vector3Test::swizzleType() { constexpr Vector<4, Int> orig; constexpr auto b = gather<'y', 'z', 'a'>(orig); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); } void Vector3Test::debug() { diff --git a/src/Magnum/Math/Test/Vector4Test.cpp b/src/Magnum/Math/Test/Vector4Test.cpp index 1c04870c7..4fc6e503a 100644 --- a/src/Magnum/Math/Test/Vector4Test.cpp +++ b/src/Magnum/Math/Test/Vector4Test.cpp @@ -112,7 +112,7 @@ void Vector4Test::construct() { constexpr Vector4 a = {1.0f, -2.5f, 3.0f, 4.1f}; CORRADE_COMPARE(a, (Vector<4, Float>(1.0f, -2.5f, 3.0f, 4.1f))); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector4Test::constructPad() { @@ -138,10 +138,10 @@ void Vector4Test::constructDefault() { CORRADE_COMPARE(b, Vector4(0.0f, 0.0f, 0.0f, 0.0f)); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector4Test::constructNoInit() { @@ -154,10 +154,10 @@ void Vector4Test::constructNoInit() { CORRADE_COMPARE(a, (Vector4{1.0f, -2.5f, 3.0f, 4.1f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector4Test::constructOneValue() { @@ -165,9 +165,9 @@ void Vector4Test::constructOneValue() { CORRADE_COMPARE(a, Vector4(4.3f, 4.3f, 4.3f, 4.3f)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector4Test::constructParts() { @@ -175,7 +175,7 @@ void Vector4Test::constructParts() { constexpr Vector4 b = {a, 4.0f}; CORRADE_COMPARE(b, Vector4(1.0f, 2.0f, 3.0f, 4.0f)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector4Test::constructConversion() { @@ -184,9 +184,9 @@ void Vector4Test::constructConversion() { CORRADE_COMPARE(b, Vector4i(1, -2, 3, 4)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void Vector4Test::constructCopy() { @@ -215,8 +215,8 @@ void Vector4Test::convert() { CORRADE_COMPARE(d.w, a.w); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void Vector4Test::access() { @@ -319,7 +319,7 @@ void Vector4Test::strictWeakOrdering() { void Vector4Test::swizzleType() { constexpr Vector4i orig; constexpr auto c = gather<'y', 'a', 'y', 'x'>(orig); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); } void Vector4Test::debug() { diff --git a/src/Magnum/Math/Test/VectorTest.cpp b/src/Magnum/Math/Test/VectorTest.cpp index b1718cf77..509a6e34b 100644 --- a/src/Magnum/Math/Test/VectorTest.cpp +++ b/src/Magnum/Math/Test/VectorTest.cpp @@ -197,7 +197,7 @@ void VectorTest::construct() { constexpr Vector4 a = {1.0f, 2.0f, -3.0f, 4.5f}; CORRADE_COMPARE(a, Vector4(1.0f, 2.0f, -3.0f, 4.5f)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void VectorTest::constructFromData() { @@ -231,10 +231,10 @@ void VectorTest::constructDefault() { CORRADE_COMPARE(b, Vector4(0.0f, 0.0f, 0.0f, 0.0f)); CORRADE_VERIFY(std::is_nothrow_default_constructible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void VectorTest::constructNoInit() { @@ -247,10 +247,10 @@ void VectorTest::constructNoInit() { CORRADE_COMPARE(a, (Vector4{1.0f, 2.0f, -3.0f, 4.5f})); } - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void VectorTest::constructOneValue() { @@ -259,9 +259,9 @@ void VectorTest::constructOneValue() { CORRADE_COMPARE(a, Vector4(7.25f, 7.25f, 7.25f, 7.25f)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void VectorTest::constructOneComponent() { @@ -271,7 +271,7 @@ void VectorTest::constructOneComponent() { constexpr Vector1 vec = 1.0f; CORRADE_COMPARE(vec, Vector1(1)); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void VectorTest::constructConversion() { @@ -281,9 +281,9 @@ void VectorTest::constructConversion() { CORRADE_COMPARE(b, Vector4i(1, 2, -15, 7)); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); } void VectorTest::constructCopy() { @@ -310,8 +310,8 @@ void VectorTest::convert() { CORRADE_COMPARE(d.z, a.z); /* Implicit conversion is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void VectorTest::isZeroFloat() { @@ -321,8 +321,8 @@ void VectorTest::isZeroFloat() { } void VectorTest::isZeroInteger() { - CORRADE_VERIFY(!(Math::Vector<3, Int>{0, 1, 0}.isZero())); - CORRADE_VERIFY((Math::Vector<3, Int>{0, 0, 0}.isZero())); + CORRADE_VERIFY(!Math::Vector<3, Int>{0, 1, 0}.isZero()); + CORRADE_VERIFY(Math::Vector<3, Int>{0, 0, 0}.isZero()); } void VectorTest::isNormalized() { @@ -630,71 +630,71 @@ typedef BasicVec2 Vec2i; void VectorTest::subclassTypes() { Float* const data = nullptr; const Float* const cdata = nullptr; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); Vector<1, Float> one; - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); /* Const operators */ const Vec2 c; const Vec2 c2; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); /* Assignment operators */ Vec2 a; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); /* Modulo operations */ const Vec2i ci; Vec2i i; const Int j = {}; - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); /* Bitwise operations */ - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same> 1), Vec2i>::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same>= 1), Vec2i&>::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same> 1), Vec2i>::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same>= 1), Vec2i&>::value); /* Integer multiplication/division */ - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); /* Functions */ - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); } void VectorTest::subclass() { diff --git a/src/Magnum/Test/ArrayTest.cpp b/src/Magnum/Test/ArrayTest.cpp index 38c8fb9e8..6b9970333 100644 --- a/src/Magnum/Test/ArrayTest.cpp +++ b/src/Magnum/Test/ArrayTest.cpp @@ -78,8 +78,8 @@ void ArrayTest::construct() { } void ArrayTest::equality() { - CORRADE_VERIFY((Array<3, Int>(5, 6, 7) == Array<3, Int>(5, 6, 7))); - CORRADE_VERIFY((Array<3, Int>(5, 6, 7) != Array<3, Int>(5, 6, 8))); + CORRADE_VERIFY(Array<3, Int>(5, 6, 7) == Array<3, Int>(5, 6, 7)); + CORRADE_VERIFY(Array<3, Int>(5, 6, 7) != Array<3, Int>(5, 6, 8)); } void ArrayTest::access() { diff --git a/src/Magnum/Test/ImageViewTest.cpp b/src/Magnum/Test/ImageViewTest.cpp index 1418de59e..92d737a57 100644 --- a/src/Magnum/Test/ImageViewTest.cpp +++ b/src/Magnum/Test/ImageViewTest.cpp @@ -477,9 +477,9 @@ void ImageViewTest::construct3DFrom1D() { /* Conversion the other way is not allowed (will be later, but explicitly via a slice<1>() like with StridedArrayView); conversion from const to mutable is not possible either */ - CORRADE_VERIFY((std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageViewTest::construct3DFrom2D() { @@ -506,8 +506,8 @@ void ImageViewTest::construct3DFrom2D() { /* Conversion the other way is not allowed (will be later, but explicitly via a slice<1>() like with StridedArrayView) */ - CORRADE_VERIFY((std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageViewTest::constructCompressed3DFrom1D() { @@ -534,9 +534,9 @@ void ImageViewTest::constructCompressed3DFrom1D() { /* Conversion the other way is not allowed (will be later, but explicitly via a slice<1>() like with StridedArrayView); conversion from const to mutable is not possible either */ - CORRADE_VERIFY((std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageViewTest::constructCompressed3DFrom2D() { @@ -560,8 +560,8 @@ void ImageViewTest::constructCompressed3DFrom2D() { /* Conversion the other way is not allowed (will be later, but explicitly via a slice<1>() like with StridedArrayView) */ - CORRADE_VERIFY((std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageViewTest::constructFromMutable() { diff --git a/src/Magnum/Test/TagsTest.cpp b/src/Magnum/Test/TagsTest.cpp index 243c1bce6..a245fc0e7 100644 --- a/src/Magnum/Test/TagsTest.cpp +++ b/src/Magnum/Test/TagsTest.cpp @@ -49,9 +49,9 @@ void TagsTest::noDefaultConstructor() { } void TagsTest::inlineDefinition() { - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); - CORRADE_VERIFY((std::is_same::value)); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); + CORRADE_VERIFY(std::is_same::value); } }}} diff --git a/src/Magnum/Vk/Test/BufferTest.cpp b/src/Magnum/Vk/Test/BufferTest.cpp index 673b902eb..1a95326b3 100644 --- a/src/Magnum/Vk/Test/BufferTest.cpp +++ b/src/Magnum/Vk/Test/BufferTest.cpp @@ -120,10 +120,10 @@ void BufferTest::createInfoConstructNoInit() { new(&info) BufferCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BufferTest::createInfoConstructFromVk() { @@ -141,7 +141,7 @@ void BufferTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BufferTest::constructCopy() { @@ -176,10 +176,10 @@ void BufferTest::bufferCopyConstructNoInit() { new(©) BufferCopy{NoInit}; CORRADE_COMPARE(copy->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } template void BufferTest::bufferCopyConstructFromVk() { @@ -242,10 +242,10 @@ void BufferTest::copyBufferInfoConstructNoInit() { new(&info) CopyBufferInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void BufferTest::copyBufferInfoConstructFromVk() { diff --git a/src/Magnum/Vk/Test/CommandBufferTest.cpp b/src/Magnum/Vk/Test/CommandBufferTest.cpp index b7c83f229..ea76ae62b 100644 --- a/src/Magnum/Vk/Test/CommandBufferTest.cpp +++ b/src/Magnum/Vk/Test/CommandBufferTest.cpp @@ -61,10 +61,10 @@ void CommandBufferTest::beginInfoConstructNoInit() { new(&info) CommandBufferBeginInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CommandBufferTest::beginInfoConstructFromVk() { @@ -82,7 +82,7 @@ void CommandBufferTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CommandBufferTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/CommandPoolTest.cpp b/src/Magnum/Vk/Test/CommandPoolTest.cpp index 77db008ad..f2c22ef59 100644 --- a/src/Magnum/Vk/Test/CommandPoolTest.cpp +++ b/src/Magnum/Vk/Test/CommandPoolTest.cpp @@ -62,10 +62,10 @@ void CommandPoolTest::createInfoConstructNoInit() { new(&info) CommandPoolCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CommandPoolTest::createInfoConstructFromVk() { @@ -83,7 +83,7 @@ void CommandPoolTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void CommandPoolTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/DevicePropertiesTest.cpp b/src/Magnum/Vk/Test/DevicePropertiesTest.cpp index 8435a7a7a..383bb8741 100644 --- a/src/Magnum/Vk/Test/DevicePropertiesTest.cpp +++ b/src/Magnum/Vk/Test/DevicePropertiesTest.cpp @@ -64,7 +64,7 @@ void DevicePropertiesTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DevicePropertiesTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/DeviceTest.cpp b/src/Magnum/Vk/Test/DeviceTest.cpp index e5f26e5db..71739b9d9 100644 --- a/src/Magnum/Vk/Test/DeviceTest.cpp +++ b/src/Magnum/Vk/Test/DeviceTest.cpp @@ -56,10 +56,10 @@ void DeviceTest::createInfoConstructNoInit() { new(&info) DeviceCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DeviceTest::createInfoConstructFromVk() { @@ -79,7 +79,7 @@ void DeviceTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void DeviceTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/DeviceVkTest.cpp b/src/Magnum/Vk/Test/DeviceVkTest.cpp index a1a67fbf7..1cf2e8787 100644 --- a/src/Magnum/Vk/Test/DeviceVkTest.cpp +++ b/src/Magnum/Vk/Test/DeviceVkTest.cpp @@ -498,8 +498,8 @@ void DeviceVkTest::createInfoWrongQueueOutputCount() { } void DeviceVkTest::createInfoConstructCopy() { - CORRADE_VERIFY(!(std::is_copy_constructible{})); - CORRADE_VERIFY(!(std::is_copy_assignable{})); + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); } void DeviceVkTest::createInfoConstructMove() { diff --git a/src/Magnum/Vk/Test/ExtensionPropertiesTest.cpp b/src/Magnum/Vk/Test/ExtensionPropertiesTest.cpp index 744d73f35..9a486d82b 100644 --- a/src/Magnum/Vk/Test/ExtensionPropertiesTest.cpp +++ b/src/Magnum/Vk/Test/ExtensionPropertiesTest.cpp @@ -54,7 +54,7 @@ void ExtensionPropertiesTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ExtensionPropertiesTest::constructInstanceNoCreate() { @@ -64,7 +64,7 @@ void ExtensionPropertiesTest::constructInstanceNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ExtensionPropertiesTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/ExtensionsTest.cpp b/src/Magnum/Vk/Test/ExtensionsTest.cpp index 17639045f..f9b6cb3f5 100644 --- a/src/Magnum/Vk/Test/ExtensionsTest.cpp +++ b/src/Magnum/Vk/Test/ExtensionsTest.cpp @@ -65,22 +65,22 @@ void ExtensionsTest::isInstanceExtension() { /* Variadic check (used in variadic addEnabledExtensions()), check that it properly fails for each occurence of a device extension */ - CORRADE_VERIFY((Implementation::IsInstanceExtension< + CORRADE_VERIFY(Implementation::IsInstanceExtension< Extensions::KHR::get_physical_device_properties2, Extensions::KHR::external_memory_capabilities, - Extensions::KHR::external_fence_capabilities>::value)); - CORRADE_VERIFY(!(Implementation::IsInstanceExtension< + Extensions::KHR::external_fence_capabilities>::value); + CORRADE_VERIFY(!Implementation::IsInstanceExtension< Extensions::KHR::draw_indirect_count, /* not */ Extensions::KHR::external_memory_capabilities, - Extensions::KHR::external_fence_capabilities>::value)); - CORRADE_VERIFY(!(Implementation::IsInstanceExtension< + Extensions::KHR::external_fence_capabilities>::value); + CORRADE_VERIFY(!Implementation::IsInstanceExtension< Extensions::KHR::get_physical_device_properties2, Extensions::KHR::external_memory, /* not */ - Extensions::KHR::external_fence_capabilities>::value)); - CORRADE_VERIFY(!(Implementation::IsInstanceExtension< + Extensions::KHR::external_fence_capabilities>::value); + CORRADE_VERIFY(!Implementation::IsInstanceExtension< Extensions::KHR::get_physical_device_properties2, Extensions::KHR::external_memory_capabilities, - Extensions::KHR::external_fence>::value)); /* not */ + Extensions::KHR::external_fence>::value); /* not */ /* Empty variadic list should return true */ CORRADE_VERIFY(Implementation::IsInstanceExtension<>::value); @@ -104,22 +104,22 @@ void ExtensionsTest::isExtension() { /* Variadic check (used in variadic addEnabledExtensions()), check that it properly fails for each occurence of a device extension */ - CORRADE_VERIFY((Implementation::IsExtension< + CORRADE_VERIFY(Implementation::IsExtension< Extensions::KHR::external_memory, Extensions::KHR::depth_stencil_resolve, - Extensions::KHR::external_fence>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::KHR::external_fence>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extensions::KHR::external_memory_capabilities, /* not */ Extensions::KHR::depth_stencil_resolve, - Extensions::KHR::external_fence>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::KHR::external_fence>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extensions::KHR::external_memory, Extensions::EXT::debug_report, /* not */ - Extensions::KHR::external_fence>::value)); - CORRADE_VERIFY(!(Implementation::IsExtension< + Extensions::KHR::external_fence>::value); + CORRADE_VERIFY(!Implementation::IsExtension< Extensions::KHR::external_memory, Extensions::KHR::depth_stencil_resolve, - Extensions::KHR::external_fence_capabilities>::value)); /* not */ + Extensions::KHR::external_fence_capabilities>::value); /* not */ /* Empty variadic list should return true */ CORRADE_VERIFY(Implementation::IsExtension<>::value); @@ -133,12 +133,12 @@ void ExtensionsTest::constructInstanceExtensionFromCompileTimeExtension() { CORRADE_COMPARE(a.string(), Extensions::KHR::get_physical_device_properties2::string()); /* Should be convertible from device extensions, but not instance exts */ - CORRADE_VERIFY((std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); /* Shouldn't be convertible from strings to avoid ambiguity in APIs that have string/extension overloads */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ExtensionsTest::constructExtensionFromCompileTimeExtension() { @@ -149,12 +149,12 @@ void ExtensionsTest::constructExtensionFromCompileTimeExtension() { CORRADE_COMPARE(a.string(), Extensions::KHR::external_memory::string()); /* Should be convertible from device extensions, but not instance exts */ - CORRADE_VERIFY((std::is_convertible::value)); - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(std::is_convertible::value); + CORRADE_VERIFY(!std::is_convertible::value); /* Shouldn't be convertible from strings to avoid ambiguity in APIs that have string/extension overloads */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ExtensionsTest::instanceExtensions() { diff --git a/src/Magnum/Vk/Test/FenceTest.cpp b/src/Magnum/Vk/Test/FenceTest.cpp index 84462e46c..6f0942a89 100644 --- a/src/Magnum/Vk/Test/FenceTest.cpp +++ b/src/Magnum/Vk/Test/FenceTest.cpp @@ -61,10 +61,10 @@ void FenceTest::createInfoConstructNoInit() { new(&info) FenceCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void FenceTest::createInfoConstructFromVk() { @@ -82,7 +82,7 @@ void FenceTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void FenceTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/FramebufferTest.cpp b/src/Magnum/Vk/Test/FramebufferTest.cpp index 827ba4103..279fa3c42 100644 --- a/src/Magnum/Vk/Test/FramebufferTest.cpp +++ b/src/Magnum/Vk/Test/FramebufferTest.cpp @@ -108,10 +108,10 @@ void FramebufferTest::createInfoConstructNoInit() { new(&info) FramebufferCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void FramebufferTest::createInfoConstructFromVk() { @@ -123,8 +123,8 @@ void FramebufferTest::createInfoConstructFromVk() { } void FramebufferTest::createInfoConstructCopy() { - CORRADE_VERIFY(!(std::is_copy_constructible{})); - CORRADE_VERIFY(!(std::is_copy_assignable{})); + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); } void FramebufferTest::createInfoConstructMove() { @@ -162,7 +162,7 @@ void FramebufferTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void FramebufferTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/ImageTest.cpp b/src/Magnum/Vk/Test/ImageTest.cpp index 36d5894be..1013fcf0a 100644 --- a/src/Magnum/Vk/Test/ImageTest.cpp +++ b/src/Magnum/Vk/Test/ImageTest.cpp @@ -327,10 +327,10 @@ void ImageTest::createInfoConstructNoInit() { new(&info) ImageCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageTest::createInfoConstructFromVk() { @@ -371,7 +371,7 @@ void ImageTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageTest::constructCopy() { @@ -414,10 +414,10 @@ void ImageTest::imageCopyConstructNoInit() { new(©) ImageCopy{NoInit}; CORRADE_COMPARE(copy->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } template void ImageTest::imageCopyConstructFromVk() { @@ -510,10 +510,10 @@ void ImageTest::copyImageInfoConstructNoInit() { new(&info) CopyImageInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageTest::copyImageInfoConstructFromVk() { @@ -656,10 +656,10 @@ void ImageTest::bufferImageCopyConstructNoInit() { new(©) BufferImageCopy{NoInit}; CORRADE_COMPARE(copy->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } template void ImageTest::bufferImageCopyConstructFromVk() { @@ -744,10 +744,10 @@ void ImageTest::copyBufferToImageInfoConstructNoInit() { new(&info) CopyBufferToImageInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageTest::copyBufferToImageInfoConstructFromVk() { @@ -797,10 +797,10 @@ void ImageTest::copyImageToBufferInfoConstructNoInit() { new(&info) CopyImageToBufferInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageTest::copyImageToBufferInfoConstructFromVk() { diff --git a/src/Magnum/Vk/Test/ImageViewTest.cpp b/src/Magnum/Vk/Test/ImageViewTest.cpp index 9579788e9..257397cdc 100644 --- a/src/Magnum/Vk/Test/ImageViewTest.cpp +++ b/src/Magnum/Vk/Test/ImageViewTest.cpp @@ -405,10 +405,10 @@ void ImageViewTest::createInfoConstructNoInit() { new(&info) ImageViewCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageViewTest::createInfoConstructFromVk() { @@ -426,7 +426,7 @@ void ImageViewTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ImageViewTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/InstanceTest.cpp b/src/Magnum/Vk/Test/InstanceTest.cpp index 1289d1595..267b0947d 100644 --- a/src/Magnum/Vk/Test/InstanceTest.cpp +++ b/src/Magnum/Vk/Test/InstanceTest.cpp @@ -57,10 +57,10 @@ void InstanceTest::createInfoConstructNoInit() { new(&info) InstanceCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void InstanceTest::createInfoConstructFromVk() { @@ -71,7 +71,7 @@ void InstanceTest::createInfoConstructFromVk() { CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void InstanceTest::constructNoCreate() { @@ -83,7 +83,7 @@ void InstanceTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void InstanceTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/IntegrationTest.cpp b/src/Magnum/Vk/Test/IntegrationTest.cpp index ae8aee2d6..65aa675b6 100644 --- a/src/Magnum/Vk/Test/IntegrationTest.cpp +++ b/src/Magnum/Vk/Test/IntegrationTest.cpp @@ -217,8 +217,8 @@ void IntegrationTest::vkClearColorValue3() { /** @todo test constexpr once/if possible */ /* Conversion the ohter way not allowed */ - CORRADE_VERIFY((std::is_constructible::value)); - CORRADE_VERIFY(!(std::is_constructible::value)); + CORRADE_VERIFY(std::is_constructible::value); + CORRADE_VERIFY(!std::is_constructible::value); } void IntegrationTest::vkViewport() { diff --git a/src/Magnum/Vk/Test/LayerPropertiesTest.cpp b/src/Magnum/Vk/Test/LayerPropertiesTest.cpp index f48f16340..048e62e56 100644 --- a/src/Magnum/Vk/Test/LayerPropertiesTest.cpp +++ b/src/Magnum/Vk/Test/LayerPropertiesTest.cpp @@ -48,7 +48,7 @@ void LayerPropertiesTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void LayerPropertiesTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/MemoryTest.cpp b/src/Magnum/Vk/Test/MemoryTest.cpp index b6375a02f..d71553b85 100644 --- a/src/Magnum/Vk/Test/MemoryTest.cpp +++ b/src/Magnum/Vk/Test/MemoryTest.cpp @@ -81,10 +81,10 @@ void MemoryTest::requirementsConstructNoInit() { new(&requirements) MemoryRequirements{NoInit}; CORRADE_COMPARE(requirements->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MemoryTest::requirementsConstructFromVk() { @@ -137,10 +137,10 @@ void MemoryTest::allocateInfoConstructNoInit() { new(&info) MemoryAllocateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MemoryTest::allocateInfoConstructFromVk() { @@ -158,7 +158,7 @@ void MemoryTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MemoryTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/MeshLayoutTest.cpp b/src/Magnum/Vk/Test/MeshLayoutTest.cpp index 1520926d7..da4dc839a 100644 --- a/src/Magnum/Vk/Test/MeshLayoutTest.cpp +++ b/src/Magnum/Vk/Test/MeshLayoutTest.cpp @@ -205,10 +205,10 @@ void MeshLayoutTest::constructNoInit() { CORRADE_COMPARE(layout.vkPipelineVertexInputStateCreateInfo().sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); CORRADE_COMPARE(layout.vkPipelineInputAssemblyStateCreateInfo().sType, VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void MeshLayoutTest::constructFromVk() { diff --git a/src/Magnum/Vk/Test/PipelineLayoutTest.cpp b/src/Magnum/Vk/Test/PipelineLayoutTest.cpp index bca890674..10f19d631 100644 --- a/src/Magnum/Vk/Test/PipelineLayoutTest.cpp +++ b/src/Magnum/Vk/Test/PipelineLayoutTest.cpp @@ -62,10 +62,10 @@ void PipelineLayoutTest::createInfoConstructNoInit() { new(&info) PipelineLayoutCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineLayoutTest::createInfoConstructFromVk() { @@ -83,7 +83,7 @@ void PipelineLayoutTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineLayoutTest::constructCopy() { diff --git a/src/Magnum/Vk/Test/PipelineTest.cpp b/src/Magnum/Vk/Test/PipelineTest.cpp index 23785bcac..d34971934 100644 --- a/src/Magnum/Vk/Test/PipelineTest.cpp +++ b/src/Magnum/Vk/Test/PipelineTest.cpp @@ -224,10 +224,10 @@ void PipelineTest::rasterizationCreateInfoConstructNoInit() { new(&info) RasterizationPipelineCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineTest::rasterizationCreateInfoConstructFromVk() { @@ -581,10 +581,10 @@ void PipelineTest::computeCreateInfoConstructNoInit() { new(&info) ComputePipelineCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineTest::computeCreateInfoConstructFromVk() { @@ -602,7 +602,7 @@ void PipelineTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineTest::constructCopy() { @@ -622,10 +622,10 @@ void PipelineTest::memoryBarrierConstructNoInit() { new(&barrier) MemoryBarrier{NoInit}; CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineTest::memoryBarrierConstructFromVk() { @@ -651,10 +651,10 @@ void PipelineTest::bufferMemoryBarrierConstructNoInit() { new(&barrier) BufferMemoryBarrier{NoInit}; CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineTest::bufferMemoryBarrierConstructFromVk() { @@ -705,10 +705,10 @@ void PipelineTest::imageMemoryBarrierConstructNoInit() { new(&barrier) ImageMemoryBarrier{NoInit}; CORRADE_COMPARE(barrier->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void PipelineTest::imageMemoryBarrierConstructFromVk() { diff --git a/src/Magnum/Vk/Test/QueueTest.cpp b/src/Magnum/Vk/Test/QueueTest.cpp index cfe18230d..3147db1c8 100644 --- a/src/Magnum/Vk/Test/QueueTest.cpp +++ b/src/Magnum/Vk/Test/QueueTest.cpp @@ -70,7 +70,7 @@ void QueueTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void QueueTest::constructCopy() { @@ -120,10 +120,10 @@ void QueueTest::submitInfoConstructNoInit() { new(&info) SubmitInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void QueueTest::submitInfoConstructCommandBuffers() { @@ -148,8 +148,8 @@ void QueueTest::submitInfoConstructFromVk() { } void QueueTest::submitInfoConstructCopy() { - CORRADE_VERIFY(!(std::is_copy_constructible{})); - CORRADE_VERIFY(!(std::is_copy_assignable{})); + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); } void QueueTest::submitInfoConstructMove() { diff --git a/src/Magnum/Vk/Test/RenderPassTest.cpp b/src/Magnum/Vk/Test/RenderPassTest.cpp index c0cf0d448..2432b49a0 100644 --- a/src/Magnum/Vk/Test/RenderPassTest.cpp +++ b/src/Magnum/Vk/Test/RenderPassTest.cpp @@ -296,10 +296,10 @@ void RenderPassTest::attachmentDescriptionConstructNoInit() { new(&description) AttachmentDescription{NoInit}; CORRADE_COMPARE(description->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } template void RenderPassTest::attachmentDescriptionConstructFromVk() { @@ -381,10 +381,10 @@ void RenderPassTest::attachmentReferenceConstructNoInit() { new(&reference) AttachmentReference{NoInit}; CORRADE_COMPARE(reference->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } template void RenderPassTest::attachmentReferenceConstructFromVk() { @@ -443,10 +443,10 @@ void RenderPassTest::subpassDescriptionConstructNoInit() { new(&description) SubpassDescription{NoInit}; CORRADE_COMPARE(description->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RenderPassTest::subpassDescriptionConstructInputAttachments() { @@ -619,8 +619,8 @@ template void RenderPassTest::subpassDescriptionConstructF } void RenderPassTest::subpassDescriptionConstructCopy() { - CORRADE_VERIFY(!(std::is_copy_constructible{})); - CORRADE_VERIFY(!(std::is_copy_assignable{})); + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); } void RenderPassTest::subpassDescriptionConstructMove() { @@ -795,10 +795,10 @@ void RenderPassTest::subpassDependencyConstructNoInit() { new(&dependency) SubpassDependency{NoInit}; CORRADE_COMPARE(dependency->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } template void RenderPassTest::subpassDependencyConstructFromVk() { @@ -876,10 +876,10 @@ void RenderPassTest::createInfoConstructNoInit() { new(&info) RenderPassCreateInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RenderPassTest::createInfoConstructAttachments() { @@ -1121,7 +1121,7 @@ void RenderPassTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RenderPassTest::constructCopy() { @@ -1174,10 +1174,10 @@ void RenderPassTest::beginInfoConstructNoInit() { new(&info) RenderPassBeginInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RenderPassTest::beginInfoConstructClears() { @@ -1206,8 +1206,8 @@ void RenderPassTest::beginInfoConstructFromVk() { } void RenderPassTest::beginInfoConstructCopy() { - CORRADE_VERIFY(!(std::is_copy_constructible{})); - CORRADE_VERIFY(!(std::is_copy_assignable{})); + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); } void RenderPassTest::beginInfoConstructMove() { @@ -1244,10 +1244,10 @@ void RenderPassTest::subpassBeginInfoConstructNoInit() { new(&info) SubpassBeginInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RenderPassTest::subpassBeginInfoConstructFromVk() { @@ -1269,10 +1269,10 @@ void RenderPassTest::subpassEndInfoConstructNoInit() { new(&info) SubpassEndInfo{NoInit}; CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void RenderPassTest::subpassEndInfoConstructFromVk() { diff --git a/src/Magnum/Vk/Test/ShaderTest.cpp b/src/Magnum/Vk/Test/ShaderTest.cpp index 6b236649e..5f1c804f7 100644 --- a/src/Magnum/Vk/Test/ShaderTest.cpp +++ b/src/Magnum/Vk/Test/ShaderTest.cpp @@ -218,10 +218,10 @@ void ShaderTest::createInfoConstructNoInit() { /* The deleter should be zero-init'd and thus no function called on destruction */ - CORRADE_VERIFY((std::is_nothrow_constructible::value)); + CORRADE_VERIFY(std::is_nothrow_constructible::value); /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ShaderTest::createInfoConstructFromVk() { @@ -287,12 +287,12 @@ void ShaderTest::constructNoCreate() { } /* Implicit construction is not allowed */ - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!std::is_convertible::value); } void ShaderTest::constructCopy() { - CORRADE_VERIFY(!(std::is_constructible{})); - CORRADE_VERIFY(!(std::is_assignable{})); + CORRADE_VERIFY(!std::is_constructible{}); + CORRADE_VERIFY(!std::is_assignable{}); } }}}} From 7f28f9f46b76ebc1a5471d9147fed5568cca0389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 11 Mar 2021 21:09:38 +0100 Subject: [PATCH 077/161] Improve backwards compatibility of the deprecated Array class. Explicitly provide conversion to Vector2 and Vector3 in addition to Vector<2> / Vector<3> as otherwise creating a TextureData from an Array3D will fail, breaking the compilation of TinyGltfImporter. --- src/Magnum/Array.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Magnum/Array.h b/src/Magnum/Array.h index 842222af4..cb115ae1d 100644 --- a/src/Magnum/Array.h +++ b/src/Magnum/Array.h @@ -184,6 +184,11 @@ template class CORRADE_DEPRECATED("use Math::Vector2 instead") Array2D /** @brief Initializer-list constructor */ constexpr /*implicit*/ Array2D(T value): Array<2, T>(value, value) {} + /** @brief Convert to a vector */ + /*implicit*/ operator Math::Vector2() const { + return Math::Vector2::from(Array<2, T>::_data); + } + T& x() { return Array<2, T>::_data[0]; } /**< @brief X component */ constexpr T x() const { return Array<2, T>::_data[0]; } /**< @overload */ T& y() { return Array<2, T>::_data[1]; } /**< @brief Y component */ @@ -214,6 +219,11 @@ template class CORRADE_DEPRECATED("use Math::Vector3 instead") Array3D: /** @brief Initializer-list constructor */ constexpr /*implicit*/ Array3D(T value): Array<3, T>(value, value, value) {} + /** @brief Convert to a vector */ + /*implicit*/ operator Math::Vector3() const { + return Math::Vector3::from(Array<3, T>::_data); + } + T& x() { return Array<3, T>::_data[0]; } /**< @brief X component */ constexpr T x() const { return Array<3, T>::_data[0]; } /**< @overload */ T& y() { return Array<3, T>::_data[1]; } /**< @brief Y component */ From ae9ff0ae285691d038c88c8ad4a5a86ff93daa9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 7 Mar 2021 22:10:14 +0100 Subject: [PATCH 078/161] Vk: implement a Sampler wrapper. Together with SamplerFilter, SamplerMipmap and SamplerWrapping enums convertible from the generic versions, which finally deprecate the last remaining vk*() conversion functions in Enums.h and thus the whole header as well. The EnumsTest executable is also no more, as the rest of it now resides inside SamplerTest. --- doc/snippets/MagnumVk.cpp | 25 +++ doc/vulkan-mapping.dox | 14 +- src/Magnum/Sampler.h | 52 +++-- src/Magnum/Vk/CMakeLists.txt | 10 +- src/Magnum/Vk/Enums.cpp | 58 +---- src/Magnum/Vk/Enums.h | 79 ++++--- src/Magnum/Vk/Sampler.cpp | 242 +++++++++++++++++++++ src/Magnum/Vk/Sampler.h | 145 +++++++++++++ src/Magnum/Vk/SamplerCreateInfo.h | 308 +++++++++++++++++++++++++++ src/Magnum/Vk/Test/CMakeLists.txt | 9 +- src/Magnum/Vk/Test/EnumsTest.cpp | 153 ------------- src/Magnum/Vk/Test/SamplerTest.cpp | 289 +++++++++++++++++++++++++ src/Magnum/Vk/Test/SamplerVkTest.cpp | 100 +++++++++ src/Magnum/Vk/Vk.h | 5 + 14 files changed, 1206 insertions(+), 283 deletions(-) create mode 100644 src/Magnum/Vk/Sampler.cpp create mode 100644 src/Magnum/Vk/Sampler.h create mode 100644 src/Magnum/Vk/SamplerCreateInfo.h delete mode 100644 src/Magnum/Vk/Test/EnumsTest.cpp create mode 100644 src/Magnum/Vk/Test/SamplerTest.cpp create mode 100644 src/Magnum/Vk/Test/SamplerVkTest.cpp diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index 9c419c424..06277b312 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -31,6 +31,7 @@ #include "Magnum/Magnum.h" #include "Magnum/Mesh.h" #include "Magnum/PixelFormat.h" +#include "Magnum/Sampler.h" #include "Magnum/VertexFormat.h" #include "Magnum/Math/Color.h" #include "Magnum/Vk/Assert.h" @@ -59,6 +60,7 @@ #include "Magnum/Vk/RasterizationPipelineCreateInfo.h" #include "Magnum/Vk/RenderPassCreateInfo.h" #include "Magnum/Vk/Result.h" +#include "Magnum/Vk/SamplerCreateInfo.h" #include "Magnum/Vk/ShaderCreateInfo.h" #include "Magnum/Vk/ShaderSet.h" #include "MagnumExternal/Vulkan/flextVkGlobal.h" @@ -1031,6 +1033,29 @@ cmd.begin() /* [RenderPass-usage-end] */ } +{ +Vk::Device device{NoCreate}; +/* The include should be a no-op here since it was already included above */ +/* [Sampler-creation] */ +#include + +DOXYGEN_IGNORE() + +Vk::Sampler sampler{device, Vk::SamplerCreateInfo{}}; +/* [Sampler-creation] */ +} + +{ +Vk::Device device{NoCreate}; +/* [Sampler-creation-linear] */ +Vk::Sampler sampler{device, Vk::SamplerCreateInfo{} + .setMinificationFilter(SamplerFilter::Linear, SamplerMipmap::Linear) + .setMagnificationFilter(SamplerFilter::Linear) + .setWrapping(SamplerWrapping::ClampToEdge) +}; +/* [Sampler-creation-linear] */ +} + { Vk::Device device{NoCreate}; /* The include should be a no-op here since it was already included above */ diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index f0000896e..1ab6265c7 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -77,7 +77,7 @@ Vulkan handle | Matching API @type_vk{QueryPool} | | @type_vk{Queue} | @ref Queue @type_vk{RenderPass} | @ref RenderPass -@type_vk{Sampler} | | +@type_vk{Sampler} | @ref Sampler @type_vk{SamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{Semaphore} | | @type_vk{ShaderModule} | @ref Shader @@ -205,7 +205,7 @@ Vulkan function | Matching API @fn_vk{CreatePipelineLayout}, \n @fn_vk{DestroyPipelineLayout} | @ref PipelineLayout constructor and destructor @fn_vk{CreateQueryPool}, \n @fn_vk{DestroyQueryPool} | | @fn_vk{CreateRenderPass}, \n @fn_vk{CreateRenderPass2} @m_class{m-label m-flat m-success} **KHR, 1.2**, \n @fn_vk{DestroyRenderPass} | @ref RenderPass constructor and destructor -@fn_vk{CreateSampler}, \n @fn_vk{DestroySampler} | | +@fn_vk{CreateSampler}, \n @fn_vk{DestroySampler} | @ref Sampler constructor and destructor @fn_vk{CreateSamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** , \n @fn_vk{DestroySamplerYcbcrConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{CreateSemaphore}, \n @fn_vk{DestroySemaphore} | | @fn_vk{CreateShaderModule}, \n @fn_vk{DestroyShaderModule} | @ref Shader constructor and destructor @@ -707,7 +707,7 @@ Vulkan structure | Matching API Vulkan structure | Matching API --------------------------------------- | ------------ -@type_vk{SamplerCreateInfo} | | +@type_vk{SamplerCreateInfo} | @ref SamplerCreateInfo @type_vk{SamplerReductionModeCreateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{SamplerYcbcrConversionCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{SamplerYcbcrConversionImageFormatProperties} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @@ -854,7 +854,7 @@ Vulkan enum | Matching API Vulkan enum | Matching API --------------------------------------- | ------------ -@type_vk{Filter} | only @ref vkFilter() +@type_vk{Filter} | @ref SamplerFilter @type_vk{Format} | @ref PixelFormat, @ref VertexFormat @type_vk{FormatFeatureFlagBits}, \n @type_vk{FormatFeatureFlags} | | @type_vk{FramebufferCreateFlagBits}, \n @type_vk{FramebufferCreateFlags} | @ref FramebufferCreateInfo::Flag, \n @ref FramebufferCreateInfo::Flags @@ -960,9 +960,9 @@ Vulkan enum | Matching API Vulkan enum | Matching API --------------------------------------- | ------------ @type_vk{SampleCountFlagBits}, \n @type_vk{SampleCountFlags} | not exposed, using plain integers instead -@type_vk{SamplerAddressMode} | only @ref vkSamplerAddressMode() -@type_vk{SamplerMipmapMode} | only @ref vkSamplerMipmapMode() -@type_vk{SamplerCreateFlagBits}, \n @type_vk{SamplerCreateFlags} | | +@type_vk{SamplerAddressMode} | @ref SamplerWrapping +@type_vk{SamplerMipmapMode} | @ref SamplerMipmap +@type_vk{SamplerCreateFlagBits}, \n @type_vk{SamplerCreateFlags} | @ref SamplerCreateInfo::Flag, \n @ref SamplerCreateInfo::Flags @type_vk{SamplerReductionMode} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{SamplerYcbcrModelConversion} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{SamplerYcbcrRange} @m_class{m-label m-flat m-success} **KHR, 1.1** | | diff --git a/src/Magnum/Sampler.h b/src/Magnum/Sampler.h index 97eca31cd..dd4886399 100644 --- a/src/Magnum/Sampler.h +++ b/src/Magnum/Sampler.h @@ -41,8 +41,8 @@ In case of OpenGL, corresponds to @ref GL::SamplerFilter and is convertible to it using @ref GL::samplerFilter(). See documentation of each value for more information about the mapping. -In case of Vulkan, corresponds to @type_vk_keyword{Filter} and is convertible -to it using @ref Vk::vkFilter(). See documentation of each value for more +In case of Vulkan, corresponds to @ref Vk::SamplerFilter and is convertible to +it using @ref Vk::samplerFilter(). See documentation of each value for more information about the mapping. @see @ref SamplerMipmap, @ref SamplerWrapping */ @@ -55,7 +55,7 @@ enum class SamplerFilter: UnsignedInt { * Nearest neighbor filtering. * * Corresponds to @ref GL::SamplerFilter::Nearest / - * @val_vk_keyword{FILTER_NEAREST,Filter}. + * @ref Vk::SamplerFilter::Nearest. */ Nearest = 0, @@ -63,7 +63,7 @@ enum class SamplerFilter: UnsignedInt { * Linear interpolation filtering. * * Corresponds to @ref GL::SamplerFilter::Linear / - * @val_vk_keyword{FILTER_LINEAR,Filter}. + * @ref Vk::SamplerFilter::Linear. */ Linear }; @@ -75,9 +75,9 @@ In case of OpenGL, corresponds to @ref GL::SamplerMipmap and is convertible to it using @ref GL::samplerMipmap(). See documentation of each value for more information about the mapping. -In case of Vulkan, corresponds to @type_vk_keyword{SamplerMipmapMode} and is -convertible to it using @ref Vk::vkSamplerMipmapMode(). See documentation of -each value for more information about the mapping. +In case of Vulkan, corresponds to @ref Vk::SamplerMipmap and is convertible to +it using @ref Vk::samplerMipmap(). See documentation of each value for more +information about the mapping. @see @ref SamplerFilter, @ref SamplerWrapping */ enum class SamplerMipmap: UnsignedInt { @@ -89,9 +89,8 @@ enum class SamplerMipmap: UnsignedInt { * Select base mip level * * Corresponds to @ref GL::SamplerMipmap::Base. On Vulkan, the - * corresponding mode is - * @val_vk_keyword{SAMPLER_MIPMAP_MODE_NEAREST,SamplerMipmapMode} and you - * have to configure the sampler to use just a single mipmap level. + * corresponding mode is @ref Vk::SamplerMipmap::Nearest and you have to + * configure the sampler to use just a single mipmap level. */ Base = 0, @@ -99,7 +98,7 @@ enum class SamplerMipmap: UnsignedInt { * Select nearest mip level. * * Corresponds to @ref GL::SamplerMipmap::Nearest / - * @val_vk_keyword{SAMPLER_MIPMAP_MODE_NEAREST,SamplerMipmapMode}. + * @ref Vk::SamplerMipmap::Nearest. */ Nearest, @@ -107,7 +106,7 @@ enum class SamplerMipmap: UnsignedInt { * Linear interpolation of nearest mip levels. * * Corresponds to @ref GL::SamplerMipmap::Linear / - * @val_vk_keyword{SAMPLER_MIPMAP_MODE_LINEAR,SamplerMipmapMode}. + * @ref Vk::SamplerMipmap::Linear. */ Linear }; @@ -120,10 +119,9 @@ to it using @ref GL::samplerWrapping(). See documentation of each value for more information about the mapping. Note that not every mode is available on all targets, use @ref GL::hasSamplerWrapping() to check for its presence. -In case of Vulkan, corresponds to @type_vk_keyword{SamplerAddressMode} and is -convertible to it using @ref Vk::vkSamplerAddressMode(). See documentation of -each value for more information about the mapping. Note that not every mode is available there, use @ref Vk::hasVkSamplerAddressMode() to check for its -presence. +In case of Vulkan, corresponds to @ref Vk::SamplerWrapping and is convertible +to it using @ref Vk::samplerWrapping(). See documentation of each value for +more information about the mapping. @see @ref SamplerFilter, @ref SamplerMipmap */ enum class SamplerWrapping: UnsignedInt { @@ -132,36 +130,36 @@ enum class SamplerWrapping: UnsignedInt { good default */ /** - * Repeat texture. + * Repeat the texture. * * Corresponds to @ref GL::SamplerWrapping::Repeat / - * @val_vk_keyword{SAMPLER_ADDRESS_MODE_REPEAT,SamplerAddressMode}. + * @ref Vk::SamplerWrapping::Repeat. */ Repeat = 0, /** - * Repeat mirrored texture. + * Repeat a mirrored texture. * * Corresponds to @ref GL::SamplerWrapping::MirroredRepeat / - * @val_vk_keyword{SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,SamplerAddressMode}. + * @ref Vk::SamplerWrapping::MirroredRepeat. */ MirroredRepeat, /** - * Clamp to edge. Coordinates out of the range will be clamped to - * first / last column / row in given direction. + * Clamp to edge. Coordinates out of range will be clamped to the first / + * last column / row in given direction. * * Corresponds to @ref GL::SamplerWrapping::ClampToEdge / - * @val_vk_keyword{SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,SamplerAddressMode}. + * @ref Vk::SamplerWrapping::ClampToEdge. */ ClampToEdge, /** - * Clamp to border color. Coordinates out of range will be clamped - * to border color. + * Clamp to border color. Coordinates out of range will be clamped to + * the border color. * * Corresponds to @ref GL::SamplerWrapping::ClampToBorder / - * @val_vk_keyword{SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,SamplerAddressMode}. + * @ref Vk::SamplerWrapping::ClampToBorder. */ ClampToBorder, @@ -170,7 +168,7 @@ enum class SamplerWrapping: UnsignedInt { * edge after that. * * Corresponds to @ref GL::SamplerWrapping::MirrorClampToEdge. / - * @val_vk_keyword{SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,SamplerAddressMode}. + * @ref Vk::SamplerWrapping::MirrorClampToEdge. */ MirrorClampToEdge }; diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 5b6701875..7a2a08b57 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -49,7 +49,6 @@ set(MagnumVk_GracefulAssert_SRCS Device.cpp DeviceProperties.cpp DeviceFeatures.cpp - Enums.cpp ExtensionProperties.cpp Image.cpp ImageView.cpp @@ -61,6 +60,7 @@ set(MagnumVk_GracefulAssert_SRCS Pipeline.cpp PixelFormat.cpp RenderPass.cpp + Sampler.cpp ShaderSet.cpp VertexFormat.cpp) @@ -76,7 +76,6 @@ set(MagnumVk_HEADERS DeviceCreateInfo.h DeviceFeatures.h DeviceProperties.h - Enums.h Extensions.h ExtensionProperties.h Fence.h @@ -105,6 +104,8 @@ set(MagnumVk_HEADERS RenderPass.h RenderPassCreateInfo.h Result.h + Sampler.h + SamplerCreateInfo.h Shader.h ShaderCreateInfo.h ShaderSet.h @@ -130,6 +131,11 @@ set(MagnumVk_PRIVATE_HEADERS Implementation/structureHelpers.h Implementation/vertexFormatMapping.hpp) +if(MAGNUM_BUILD_DEPRECATED) + list(APPEND MagnumVk_SRCS Enums.cpp) + list(APPEND MagnumVk_HEADERS Enums.h) +endif() + # Objects shared between main and test library add_library(MagnumVkObjects OBJECT ${MagnumVk_SRCS} diff --git a/src/Magnum/Vk/Enums.cpp b/src/Magnum/Vk/Enums.cpp index 443873d07..b464ac01c 100644 --- a/src/Magnum/Vk/Enums.cpp +++ b/src/Magnum/Vk/Enums.cpp @@ -23,46 +23,18 @@ DEALINGS IN THE SOFTWARE. */ -#include "Enums.h" - -#include +#define _MAGNUM_NO_DEPRECATED_VK_ENUMS -#include "Magnum/Mesh.h" -#include "Magnum/Sampler.h" +#include "Enums.h" -#ifdef MAGNUM_BUILD_DEPRECATED #include "Magnum/Vk/MeshLayout.h" #include "Magnum/Vk/Mesh.h" #include "Magnum/Vk/PixelFormat.h" +#include "Magnum/Vk/SamplerCreateInfo.h" #include "Magnum/Vk/VertexFormat.h" -#endif namespace Magnum { namespace Vk { -namespace { - -constexpr VkFilter FilterMapping[]{ - VK_FILTER_NEAREST, - VK_FILTER_LINEAR -}; - -constexpr VkSamplerMipmapMode SamplerMipmapModeMapping[]{ - VK_SAMPLER_MIPMAP_MODE_NEAREST, /* See vkSamplerMipmapMode() for details */ - VK_SAMPLER_MIPMAP_MODE_NEAREST, - VK_SAMPLER_MIPMAP_MODE_LINEAR -}; - -constexpr VkSamplerAddressMode SamplerAddressModeMapping[]{ - VK_SAMPLER_ADDRESS_MODE_REPEAT, - VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, - VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, -}; - -} - -#ifdef MAGNUM_BUILD_DEPRECATED bool hasVkPrimitiveTopology(const Magnum::MeshPrimitive primitive) { return hasMeshPrimitive(primitive); } @@ -71,7 +43,7 @@ VkPrimitiveTopology vkPrimitiveTopology(const Magnum::MeshPrimitive primitive) { return VkPrimitiveTopology(meshPrimitive(primitive)); } -bool hasVkIndexType(const Magnum::MeshIndexType) { +bool hasVkIndexType(Magnum::MeshIndexType) { return true; } @@ -102,33 +74,21 @@ VkFormat vkFormat(const Magnum::PixelFormat format) { VkFormat vkFormat(const Magnum::CompressedPixelFormat format) { return VkFormat(pixelFormat(format)); } -#endif VkFilter vkFilter(const Magnum::SamplerFilter filter) { - CORRADE_ASSERT(UnsignedInt(filter) < Containers::arraySize(FilterMapping), - "Vk::vkFilter(): invalid filter" << filter, {}); - return FilterMapping[UnsignedInt(filter)]; + return VkFilter(samplerFilter(filter)); } VkSamplerMipmapMode vkSamplerMipmapMode(const Magnum::SamplerMipmap mipmap) { - CORRADE_ASSERT(UnsignedInt(mipmap) < Containers::arraySize(SamplerMipmapModeMapping), - "Vk::vkSamplerMipmapMode(): invalid mode" << mipmap, {}); - return SamplerMipmapModeMapping[UnsignedInt(mipmap)]; + return VkSamplerMipmapMode(samplerMipmap(mipmap)); } -bool hasVkSamplerAddressMode(const Magnum::SamplerWrapping wrapping) { - CORRADE_ASSERT(UnsignedInt(wrapping) < Containers::arraySize(SamplerAddressModeMapping), - "Vk::hasVkSamplerAddressMode(): invalid wrapping" << wrapping, {}); - return UnsignedInt(SamplerAddressModeMapping[UnsignedInt(wrapping)]) != ~UnsignedInt{}; +bool hasVkSamplerAddressMode(Magnum::SamplerWrapping) { + return true; } VkSamplerAddressMode vkSamplerAddressMode(const Magnum::SamplerWrapping wrapping) { - CORRADE_ASSERT(UnsignedInt(wrapping) < Containers::arraySize(SamplerAddressModeMapping), - "Vk::vkSamplerAddressMode(): invalid wrapping" << wrapping, {}); - const VkSamplerAddressMode out = SamplerAddressModeMapping[UnsignedInt(wrapping)]; - CORRADE_ASSERT(out != VkSamplerAddressMode(~UnsignedInt{}), - "Vk::vkSamplerAddressMode(): unsupported wrapping" << wrapping, {}); - return out; + return VkSamplerAddressMode(samplerWrapping(wrapping)); } }} diff --git a/src/Magnum/Vk/Enums.h b/src/Magnum/Vk/Enums.h index 838f4f084..ae2174b6f 100644 --- a/src/Magnum/Vk/Enums.h +++ b/src/Magnum/Vk/Enums.h @@ -25,27 +25,31 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file * @brief Function @ref Magnum::Vk::hasVkPrimitiveTopology(), @ref Magnum::Vk::vkPrimitiveTopology(), @ref Magnum::Vk::hasVkIndexType(), @ref Magnum::Vk::vkIndexType(), @ref Magnum::Vk::hasVkFormat(), @ref Magnum::Vk::vkFormat(), @ref Magnum::Vk::vkFilter(), @ref Magnum::Vk::vkSamplerMipmapMode(), @ref Magnum::Vk::hasVkSamplerAddressMode(), @ref Magnum::Vk::vkSamplerAddressMode() + * @m_deprecated_since_latest All functionality in this header has been + * deprecated and moved elsewhere. Use headers corresponding to the + * suggested replacement APIs instead. */ +#endif -#include "Magnum/Magnum.h" +#include "Magnum/configure.h" + +#ifdef MAGNUM_BUILD_DEPRECATED +#include "Magnum/Array.h" /* That's fine, we're deprecated too */ #include "Magnum/Math/Vector3.h" #include "Magnum/Vk/Vulkan.h" #include "Magnum/Vk/visibility.h" -#ifdef MAGNUM_BUILD_DEPRECATED #include -#endif -#ifdef MAGNUM_BUILD_DEPRECATED -/* For implicit conversions to Vector, not used otherwise */ -#include "Magnum/Array.h" +#ifndef _MAGNUM_NO_DEPRECATED_VK_ENUMS +CORRADE_DEPRECATED_FILE("use headers corresponding to the suggested replacement APIs instead") #endif namespace Magnum { namespace Vk { -#ifdef MAGNUM_BUILD_DEPRECATED /** * @brief @copybrief hasMeshPrimitive() * @m_deprecated_since_latest Use @ref hasMeshPrimitive() instead. @@ -109,51 +113,37 @@ CORRADE_DEPRECATED("use pixelFormat() instead") MAGNUM_VK_EXPORT VkFormat vkForm * instead. */ CORRADE_DEPRECATED("use pixelFormat() instead") MAGNUM_VK_EXPORT VkFormat vkFormat(Magnum::CompressedPixelFormat format); -#endif /** -@brief Convert generic sampler filter to Vulkan filter - -@see @ref vkSamplerMipmapMode(), @ref vkSamplerAddressMode() -*/ -MAGNUM_VK_EXPORT VkFilter vkFilter(Magnum::SamplerFilter filter); + * @brief @copybrief samplerFilter() + * @m_deprecated_since_latest Use @ref samplerFilter() instead. + */ +CORRADE_DEPRECATED("use samplerFilter() instead") MAGNUM_VK_EXPORT VkFilter vkFilter(Magnum::SamplerFilter filter); /** -@brief Convert generic sampler mipomap mode to Vulkan sampler mipmap mode - -Vulkan doesn't support the @ref SamplerMipmap::Base value directly, instead -@val_vk{SAMPLER_MIPMAP_MODE_NEAREST,SamplerMipmapMode} is used and you have to -configure the sampler to use just a single mipmap level. -@see @ref vkFilter(), @ref vkSamplerAddressMode() -*/ -MAGNUM_VK_EXPORT VkSamplerMipmapMode vkSamplerMipmapMode(Magnum::SamplerMipmap mipmap); + * @brief @copybrief samplerMipmap() + * @m_deprecated_since_latest Use @ref samplerMipmap() instead. + */ +CORRADE_DEPRECATED("use samplerMipmap() instead") MAGNUM_VK_EXPORT VkSamplerMipmapMode vkSamplerMipmapMode(Magnum::SamplerMipmap mipmap); /** -@brief Check availability of a generic sampler wrapping mode - -Returns @cpp false @ce if Vulkan doesn't support such wrapping, @cpp true @ce -otherwise. The @p wrapping value is expected to be valid. - -@note Support of some modes depends on presence of a particular Vulkan - extension. Such check is outside of the scope of this function and you are - expected to verify extension availability before using such mode. - -@see @ref vkSamplerAddressMode(), @ref vkFilter(), @ref vkSamplerMipmapMode() -*/ -MAGNUM_VK_EXPORT bool hasVkSamplerAddressMode(Magnum::SamplerWrapping wrapping); + * @brief Check availability of a generic sampler wrapping mode + * @m_deprecated_since_latest All generic sampler wrapping modes are available + * in Vulkan. + */ +CORRADE_DEPRECATED("all generic sampler wrapping modes are available in Vulkan") MAGNUM_VK_EXPORT bool hasVkSamplerAddressMode(Magnum::SamplerWrapping wrapping); /** -@brief Convert generic sampler filter mode to Vulkan sampler address mode - -Not all generic sampler wrapping modes have a Vulkan equivalent and this -function expects that given mode is available. Use @ref hasVkSamplerAddressMode() -to query availability of given mode. -@see @ref vkFilter(), @ref vkSamplerAddressMode() -*/ -MAGNUM_VK_EXPORT VkSamplerAddressMode vkSamplerAddressMode(Magnum::SamplerWrapping wrapping); + * @brief @copybrief samplerWrapping() + * @m_deprecated_since_latest Use @ref samplerWrapping() instead. + */ +CORRADE_DEPRECATED("use samplerWrapping() instead") MAGNUM_VK_EXPORT VkSamplerAddressMode vkSamplerAddressMode(Magnum::SamplerWrapping wrapping); -/** @overload */ -template Math::Vector vkSamplerAddressMode(const Math::Vector& wrapping) { +/** + * @brief @copybrief samplerWrapping() + * @m_deprecated_since_latest Use @ref samplerWrapping() instead. + */ +template CORRADE_DEPRECATED("use samplerWrapping() instead") Math::Vector vkSamplerAddressMode(const Math::Vector& wrapping) { Math::Vector out{NoInit}; for(std::size_t i = 0; i != dimensions; ++i) out[i] = vkSamplerAddressMode(wrapping[i]); @@ -161,5 +151,8 @@ template Math::Vector } }} +#else +#error use headers corresponding to the suggested replacement APIs instead +#endif #endif diff --git a/src/Magnum/Vk/Sampler.cpp b/src/Magnum/Vk/Sampler.cpp new file mode 100644 index 000000000..4e2b51cb8 --- /dev/null +++ b/src/Magnum/Vk/Sampler.cpp @@ -0,0 +1,242 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 "Sampler.h" +#include "SamplerCreateInfo.h" + +#include + +#include "Magnum/Sampler.h" +#include "Magnum/Math/Vector3.h" +#include "Magnum/Vk/Assert.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/Result.h" + +namespace Magnum { namespace Vk { + +namespace { + +constexpr SamplerFilter FilterMapping[]{ + SamplerFilter::Nearest, + SamplerFilter::Linear +}; + +constexpr SamplerMipmap SamplerMipmapMapping[]{ + SamplerMipmap::Nearest, /* See samplerMipmap() for details */ + SamplerMipmap::Nearest, + SamplerMipmap::Linear +}; + +constexpr SamplerWrapping SamplerWrappingMapping[]{ + SamplerWrapping::Repeat, + SamplerWrapping::MirroredRepeat, + SamplerWrapping::ClampToEdge, + SamplerWrapping::ClampToBorder, + SamplerWrapping::MirrorClampToEdge +}; + +} + +SamplerFilter samplerFilter(const Magnum::SamplerFilter filter) { + CORRADE_ASSERT(UnsignedInt(filter) < Containers::arraySize(FilterMapping), + "Vk::samplerFilter(): invalid filter" << filter, {}); + return FilterMapping[UnsignedInt(filter)]; +} + +SamplerMipmap samplerMipmap(const Magnum::SamplerMipmap mipmap) { + CORRADE_ASSERT(UnsignedInt(mipmap) < Containers::arraySize(SamplerMipmapMapping), + "Vk::samplerMipmap(): invalid mode" << mipmap, {}); + return SamplerMipmapMapping[UnsignedInt(mipmap)]; +} + +SamplerWrapping samplerWrapping(const Magnum::SamplerWrapping wrapping) { + CORRADE_ASSERT(UnsignedInt(wrapping) < Containers::arraySize(SamplerWrappingMapping), + "Vk::samplerWrapping(): invalid wrapping" << wrapping, {}); + return SamplerWrappingMapping[UnsignedInt(wrapping)]; +} + +template Math::Vector samplerWrapping(const Math::Vector& wrapping) { + Math::Vector out{NoInit}; + for(std::size_t i = 0; i != dimensions; ++i) + out[i] = samplerWrapping(wrapping[i]); + return out; +} + +/* Export needed by MSVC, for others it's enough to have on the declaration in + the header */ +template MAGNUM_VK_EXPORT Math::Vector<1, SamplerWrapping> samplerWrapping(const Math::Vector<1, Magnum::SamplerWrapping>&); +template MAGNUM_VK_EXPORT Math::Vector<2, SamplerWrapping> samplerWrapping(const Math::Vector<2, Magnum::SamplerWrapping>&); +template MAGNUM_VK_EXPORT Math::Vector<3, SamplerWrapping> samplerWrapping(const Math::Vector<3, Magnum::SamplerWrapping>&); + +Debug& operator<<(Debug& debug, const SamplerFilter value) { + debug << "Vk::SamplerFilter" << Debug::nospace; + + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Vk::SamplerFilter::value: return debug << "::" << Debug::nospace << #value; + _c(Nearest) + _c(Linear) + #undef _c + /* LCOV_EXCL_STOP */ + } + + /* Vulkan docs have the values in decimal, so not converting to hex */ + return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; +} + +Debug& operator<<(Debug& debug, const SamplerMipmap value) { + debug << "Vk::SamplerMipmap" << Debug::nospace; + + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Vk::SamplerMipmap::value: return debug << "::" << Debug::nospace << #value; + _c(Nearest) + _c(Linear) + #undef _c + /* LCOV_EXCL_STOP */ + } + + /* Vulkan docs have the values in decimal, so not converting to hex */ + return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; +} + +Debug& operator<<(Debug& debug, const SamplerWrapping value) { + debug << "Vk::SamplerWrapping" << Debug::nospace; + + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Vk::SamplerWrapping::value: return debug << "::" << Debug::nospace << #value; + _c(Repeat) + _c(MirroredRepeat) + _c(ClampToEdge) + _c(ClampToBorder) + _c(MirrorClampToEdge) + #undef _c + /* LCOV_EXCL_STOP */ + } + + /* Vulkan docs have the values in decimal, so not converting to hex */ + return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; +} + +SamplerCreateInfo::SamplerCreateInfo(const Flags flags): _info{} { + _info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + _info.flags = VkDescriptorSetLayoutCreateFlags(flags); + _info.minFilter = VkFilter(SamplerFilter::Nearest); + _info.magFilter = VkFilter(SamplerFilter::Nearest); + /* These are 0, which makes them the obvious candidates, however it's also + helpful in case the texture coordinates are completely off -- with + ClampToEdge (that I wanted to use at first) it would make debugging much + harder as the output could be just a single color in worst cases */ + _info.addressModeU = VkSamplerAddressMode(SamplerWrapping::Repeat); + _info.addressModeV = VkSamplerAddressMode(SamplerWrapping::Repeat); + _info.addressModeW = VkSamplerAddressMode(SamplerWrapping::Repeat); + _info.minLod = -1000.0f; + _info.maxLod = 1000.0f; +} + +SamplerCreateInfo::SamplerCreateInfo(NoInitT) noexcept {} + +SamplerCreateInfo::SamplerCreateInfo(const VkSamplerCreateInfo& info): + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _info(info) {} + +SamplerCreateInfo& SamplerCreateInfo::setMinificationFilter(const SamplerFilter filter, const SamplerMipmap mipmap) { + _info.minFilter = VkFilter(filter); + _info.mipmapMode = VkSamplerMipmapMode(mipmap); + return *this; +} + +SamplerCreateInfo& SamplerCreateInfo::setMinificationFilter(const Magnum::SamplerFilter filter, const Magnum::SamplerMipmap mipmap) { + return setMinificationFilter(samplerFilter(filter), samplerMipmap(mipmap)); +} + +SamplerCreateInfo& SamplerCreateInfo::setMagnificationFilter(const SamplerFilter filter) { + _info.magFilter = VkFilter(filter); + return *this; +} + +SamplerCreateInfo& SamplerCreateInfo::setMagnificationFilter(const Magnum::SamplerFilter filter) { + return setMagnificationFilter(samplerFilter(filter)); +} + +SamplerCreateInfo& SamplerCreateInfo::setWrapping(const Math::Vector3& wrapping) { + _info.addressModeU = VkSamplerAddressMode(wrapping.x()); + _info.addressModeV = VkSamplerAddressMode(wrapping.y()); + _info.addressModeW = VkSamplerAddressMode(wrapping.z()); + return *this; +} + +SamplerCreateInfo& SamplerCreateInfo::setWrapping(const Math::Vector3& wrapping) { + return setWrapping(samplerWrapping(wrapping)); +} + +SamplerCreateInfo& SamplerCreateInfo::setWrapping(const SamplerWrapping wrapping) { + return setWrapping(Math::Vector3{wrapping}); +} + +SamplerCreateInfo& SamplerCreateInfo::setWrapping(const Magnum::SamplerWrapping wrapping) { + return setWrapping(Math::Vector3{wrapping}); +} + +Sampler Sampler::wrap(Device& device, const VkSampler handle, const HandleFlags flags) { + Sampler out{NoCreate}; + out._device = &device; + out._handle = handle; + out._flags = flags; + return out; +} + +Sampler::Sampler(Device& device, const SamplerCreateInfo& info): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} { + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateSampler(device, info, nullptr, &_handle)); +} + +Sampler::Sampler(NoCreateT): _device{}, _handle{} {} + +Sampler::Sampler(Sampler&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} { + other._handle = {}; +} + +Sampler::~Sampler() { + if(_handle && (_flags & HandleFlag::DestroyOnDestruction)) + (**_device).DestroySampler(*_device, _handle, nullptr); +} + +Sampler& Sampler::operator=(Sampler&& other) noexcept { + using std::swap; + swap(other._device, _device); + swap(other._handle, _handle); + swap(other._flags, _flags); + return *this; +} + +VkSampler Sampler::release() { + const VkSampler handle = _handle; + _handle = {}; + return handle; +} + +}} diff --git a/src/Magnum/Vk/Sampler.h b/src/Magnum/Vk/Sampler.h new file mode 100644 index 000000000..26ca1d36c --- /dev/null +++ b/src/Magnum/Vk/Sampler.h @@ -0,0 +1,145 @@ +#ifndef Magnum_Vk_Sampler_h +#define Magnum_Vk_Sampler_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Vk::Sampler + * @m_since_latest + */ + +#include "Magnum/Tags.h" +#include "Magnum/Vk/Handle.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Sampler +@m_since_latest + +Wraps a @type_vk_keyword{Sampler}. + +@section Vk-Sampler-creation Sampler creation + +The default-constructed @ref SamplerCreateInfo uses a conservative setup with +nearest neighbor filtering and will produce valid results with no need to set +up anything else: + +@snippet MagnumVk.cpp Sampler-creation + +Usually, however, you'll want to set up filtering and mip level selection at +least, along with other properties: + +@snippet MagnumVk.cpp Sampler-creation-linear + +*/ +class MAGNUM_VK_EXPORT Sampler { + public: + /** + * @brief Wrap existing Vulkan handle + * @param device Vulkan device the sampler is created on + * @param handle The @type_vk{Sampler} handle + * @param flags Handle flags + * + * The @p handle is expected to be originating from @p device. Unlike + * a sampler created using a constructor, the Vulkan sampler is by + * default not deleted on destruction, use @p flags for different + * behavior. + * @see @ref release() + */ + static Sampler wrap(Device& device, VkSampler handle, HandleFlags flags = {}); + + /** + * @brief Constructor + * @param device Vulkan device to create the sampler on + * @param info Sampler creation info + * + * @see @fn_vk_keyword{CreateSampler} + */ + explicit Sampler(Device& device, const SamplerCreateInfo& info); + + /** + * @brief Construct without creating the sampler + * + * The constructed instance is equivalent to moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + */ + explicit Sampler(NoCreateT); + + /** @brief Copying is not allowed */ + Sampler(const Sampler&) = delete; + + /** @brief Move constructor */ + Sampler(Sampler&& other) noexcept; + + /** + * @brief Destructor + * + * Destroys associated @type_vk{Sampler} handle, unless the instance + * was created using @ref wrap() without + * @ref HandleFlag::DestroyOnDestruction specified. + * @see @fn_vk_keyword{DestroySampler}, @ref release() + */ + ~Sampler(); + + /** @brief Copying is not allowed */ + Sampler& operator=(const Sampler&) = delete; + + /** @brief Move assignment */ + Sampler& operator=(Sampler&& other) noexcept; + + /** @brief Underlying @type_vk{Sampler} handle */ + VkSampler handle() { return _handle; } + /** @overload */ + operator VkSampler() { return _handle; } + + /** @brief Handle flags */ + HandleFlags handleFlags() const { return _flags; } + + /** + * @brief Release the underlying Vulkan sampler + * + * Releases ownership of the Vulkan sampler and returns its handle so + * @fn_vk{DestroySampler} is not called on destruction. The internal + * state is then equivalent to moved-from state. + * @see @ref wrap() + */ + VkSampler release(); + + private: + /* Can't be a reference because of the NoCreate constructor */ + Device* _device; + + VkSampler _handle; + HandleFlags _flags; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/SamplerCreateInfo.h b/src/Magnum/Vk/SamplerCreateInfo.h new file mode 100644 index 000000000..15d0256fc --- /dev/null +++ b/src/Magnum/Vk/SamplerCreateInfo.h @@ -0,0 +1,308 @@ +#ifndef Magnum_Vk_SamplerCreateInfo_h +#define Magnum_Vk_SamplerCreateInfo_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Vk::SamplerCreateInfo, enum @ref Magnum::Vk::SamplerFilter, @ref Magnum::Vk::SamplerMipmap, @ref Magnum::Vk::SamplerWrapping, function @ref Magnum::Vk::samplerFilter(), @ref Magnum::Vk::samplerMipmap(), @ref Magnum::Vk::samplerWrapping() + * @m_since_latest + */ + +#include + +#include "Magnum/Tags.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Texture sampler filtering +@m_since_latest + +Wraps a @type_vk_keyword{Filter}. +@see @ref Magnum::SamplerFilter, @ref samplerFilter(), + @ref SamplerCreateInfo::setMinificationFilter(), + @ref SamplerCreateInfo::setMagnificationFilter() +*/ +enum class SamplerFilter: Int { + /** Nearest neighbor filtering */ + Nearest = VK_FILTER_NEAREST, + + /** Linear interpolation filtering */ + Linear = VK_FILTER_LINEAR +}; + +/** +@debugoperatorenum{SamplerFilter} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, SamplerFilter value); + +/** +@brief Convert a generic sampler filter to Vulkan sampler filter +@m_since_latest + +@see @ref samplerMipmap(), @ref samplerWrapping() +*/ +MAGNUM_VK_EXPORT SamplerFilter samplerFilter(Magnum::SamplerFilter filter); + +/** +@brief Texture sampler mip level selection +@m_since_latest + +Wraps a @type_vk_keyword{SamplerMipmapMode}. +@see @ref Magnum::SamplerMipmap, @ref samplerMipmap(), + @ref SamplerCreateInfo::setMinificationFilter() +*/ +enum class SamplerMipmap: Int { + /** Select nearest mip level */ + Nearest = VK_SAMPLER_MIPMAP_MODE_NEAREST, + + /** Linear interpolation of nearest mip levels */ + Linear = VK_SAMPLER_MIPMAP_MODE_LINEAR +}; + +/** +@debugoperatorenum{SamplerWrapping} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, SamplerWrapping value); + +/** +@brief Convert a generic sampler mipmap mode to Vulkan sampler mipmap mode +@m_since_latest + +Vulkan doesn't support the @ref Magnum::SamplerMipmap::Base value directly, +instead @ref SamplerMipmap::Nearest is used and you have to configure the +sampler to use just a single mipmap level. +@see @ref samplerFilter(), @ref samplerWrapping() +*/ +MAGNUM_VK_EXPORT SamplerMipmap samplerMipmap(Magnum::SamplerMipmap mipmap); + +/** +@brief Texture sampler wrapping +@m_since_latest + +@see @ref Magnum::SamplerWrapping, @ref samplerWrapping(), + @ref SamplerCreateInfo::setWrapping() +*/ +enum class SamplerWrapping: Int { + /** Repeat the texture */ + Repeat = VK_SAMPLER_ADDRESS_MODE_REPEAT, + + /** Repeat a mirrored texture */ + MirroredRepeat = VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, + + /** + * Clamp to edge. Coordinates out of range will be clamped to the first / + * last column / row / layer in given direction. + */ + ClampToEdge = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + + /** + * Clamp to border color. Coordinates of out range will be clamped to the + * border color. + */ + ClampToBorder = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, + + /** + * Mirror the texture once in negative coordinates and clamp to edge after + * that. + * @requires_vk12 Extension @vk_extension{KHR,sampler_mirror_clamp_to_edge} + * @todoc The extension mentions something about vanilla 1.2 not having + * this unless the extension is also listed (wtf??) + */ + MirrorClampToEdge = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE +}; + +/** +@debugoperatorenum{SamplerMipmap} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, SamplerMipmap value); + +/** +@brief Convert a generic sampler wrapping mode to Vulkan sampler wrapping mode +@m_since_latest + +@see @ref samplerFilter(), @ref samplerMipmap() +*/ +MAGNUM_VK_EXPORT SamplerWrapping samplerWrapping(Magnum::SamplerWrapping wrapping); + +/** + * @brief @copybrief samplerWrapping() + * @m_deprecated_since_latest Use @ref samplerWrapping() instead. + */ +template MAGNUM_VK_EXPORT Math::Vector samplerWrapping(const Math::Vector& wrapping); + +/** +@brief Sampler creation info +@m_since_latest + +Wraps a @type_vk_keyword{SamplerCreateInfo}. See +@ref Vk-Sampler-creation "Sampler creation" for usage information. +@todo @type_vk{SamplerReductionMode}, anisotropy +*/ +class MAGNUM_VK_EXPORT SamplerCreateInfo { + public: + /** + * @brief Sampler creation flag + * + * Wraps @type_vk_keyword{SamplerCreateFlagBits}. + * @see @ref Flags, @ref SamplerCreateInfo(Flags) + * @m_enum_values_as_keywords + */ + enum class Flag: UnsignedInt { + /** @todo all the flags from extensions */ + }; + + /** + * @brief Sampler creation flags + * + * Type-safe wrapper for @type_vk_keyword{SamplerCreateFlags}. + * @see @ref SamplerCreateInfo(Flags) + */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param flags Sampler creation flags + * + * The following @type_vk{SamplerCreateInfo} fields are pre-filled in + * addition to `sType`, everything else is zero-filled: + * + * - `flags` + * - `minFilter` and `magFilter` to @ref SamplerFilter::Nearest + * - `mipmapMode` to @ref SamplerMipmap::Nearest + * - `addressModeU`, `addressModeV` and `addressModeW` to + * @ref SamplerWrapping::Repeat + * - `minLod` to @cpp -1000.0f @ce + * - `maxLod` to @cpp 1000.0f @ce + * + * The min/max LOD defaults are chosen to be the same as OpenGL + * defaults. + * @see @ref setMinificationFilter(), @ref setMagnificationFilter(), + * @ref setWrapping() + */ + explicit SamplerCreateInfo(Flags flags = {}); + + /** + * @brief Construct without initializing the contents + * + * Note that not even the `sType` field is set --- the structure has to + * be fully initialized afterwards in order to be usable. + */ + explicit SamplerCreateInfo(NoInitT) noexcept; + + /** + * @brief Construct from existing data + * + * Copies the existing values verbatim, pointers are kept unchanged + * without taking over the ownership. Modifying the newly created + * instance will not modify the original data nor the pointed-to data. + */ + explicit SamplerCreateInfo(const VkSamplerCreateInfo& info); + + /** + * @brief Set minification filter + * @return Reference to self (for method chaining) + * + * Sets the following @type_vk{SamplerCreateInfo} fields: + * + * - `minFilter` to @p filter + * - `mipmapMode` to @p mipmap + * + * @see @ref setMagnificationFilter(), @ref setWrapping() + */ + SamplerCreateInfo& setMinificationFilter(SamplerFilter filter, SamplerMipmap mipmap); + /** @overload */ + SamplerCreateInfo& setMinificationFilter(Magnum::SamplerFilter filter, Magnum::SamplerMipmap mipmap); + + /** + * @brief Set magnification filter + * @return Reference to self (for method chaining) + * + * Sets the following @type_vk{SamplerCreateInfo} fields: + * + * - `magFilter` to @p filter + * + * @see @ref setMinificationFilter(), @ref setWrapping() + */ + SamplerCreateInfo& setMagnificationFilter(SamplerFilter filter); + /** @overload */ + SamplerCreateInfo& setMagnificationFilter(Magnum::SamplerFilter filter); + + /** + * @brief Set wrapping + * @return Reference to self (for method chaining) + * + * Sets the following @type_vk{SamplerCreateInfo} fields: + * + * - `addressModeU`, `addressModeV` and `addressModeW` to + * the respective components of @p wrapping + * + * @see @ref setMinificationFilter(), @ref setMagnificationFilter() + */ + SamplerCreateInfo& setWrapping(const Math::Vector3& wrapping); + /** @overload */ + SamplerCreateInfo& setWrapping(const Math::Vector3& wrapping); + + /** + * @brief Set wrapping for all dimensions at once + * @return Reference to self (for method chaining) + * + * Same as calling @ref setWrapping(const Math::Vector3&) + * with @p wrapping set for all components. + */ + SamplerCreateInfo& setWrapping(SamplerWrapping wrapping); + /** @overload */ + SamplerCreateInfo& setWrapping(Magnum::SamplerWrapping wrapping); + + /** @brief Underlying @type_vk{SamplerCreateInfo} structure */ + VkSamplerCreateInfo& operator*() { return _info; } + /** @overload */ + const VkSamplerCreateInfo& operator*() const { return _info; } + /** @overload */ + VkSamplerCreateInfo* operator->() { return &_info; } + /** @overload */ + const VkSamplerCreateInfo* operator->() const { return &_info; } + /** @overload */ + operator const VkSamplerCreateInfo*() const { return &_info; } + + private: + VkSamplerCreateInfo _info; +}; + +CORRADE_ENUMSET_OPERATORS(SamplerCreateInfo::Flags) + +}} + +/* Make the definition complete -- it doesn't make sense to have a CreateInfo + without the corresponding object anyway. */ +#include "Magnum/Vk/Sampler.h" + +#endif diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index 7cce44722..7738e9936 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -30,7 +30,6 @@ corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceTest DeviceTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDevicePropertiesTest DevicePropertiesTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceFeaturesTest DeviceFeaturesTest.cpp LIBRARIES MagnumVk) -corrade_add_test(VkEnumsTest EnumsTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkExtensionsTest ExtensionsTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkExtensionPropertiesTest ExtensionPropertiesTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkFenceTest FenceTest.cpp LIBRARIES MagnumVk) @@ -50,6 +49,7 @@ corrade_add_test(VkPixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumVkTestLib corrade_add_test(VkQueueTest QueueTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkResultTest ResultTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkRenderPassTest RenderPassTest.cpp LIBRARIES MagnumVkTestLib) +corrade_add_test(VkSamplerTest SamplerTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkShaderTest ShaderTest.cpp LIBRARIES MagnumVk) target_include_directories(VkShaderTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) @@ -132,7 +132,6 @@ set_target_properties( VkDeviceTest VkDeviceFeaturesTest VkDevicePropertiesTest - VkEnumsTest VkExtensionsTest VkExtensionPropertiesTest VkFenceTest @@ -152,6 +151,7 @@ set_target_properties( VkQueueTest VkResultTest VkRenderPassTest + VkSamplerTest VkShaderTest VkShaderSetTest VkStructureHelpersTest @@ -226,13 +226,17 @@ if(BUILD_VK_TESTS) LIBRARIES MagnumVkTestLib MagnumVulkanTester FILES triangle-shaders.spv compute-noop.spv) target_include_directories(VkPipelineVkTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) + corrade_add_test(VkPipelineLayoutVkTest PipelineLayoutVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkQueueVkTest QueueVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkRenderPassVkTest RenderPassVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) + corrade_add_test(VkSamplerVkTest SamplerVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) + corrade_add_test(VkShaderVkTest ShaderVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester FILES triangle-shaders.spv) target_include_directories(VkShaderVkTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/$) + corrade_add_test(VkVersionVkTest VersionVkTest.cpp LIBRARIES MagnumVk) set_target_properties( @@ -254,6 +258,7 @@ if(BUILD_VK_TESTS) VkPipelineLayoutVkTest VkQueueVkTest VkRenderPassVkTest + VkSamplerVkTest VkShaderVkTest VkVersionVkTest PROPERTIES FOLDER "Magnum/Vk/Test") diff --git a/src/Magnum/Vk/Test/EnumsTest.cpp b/src/Magnum/Vk/Test/EnumsTest.cpp deleted file mode 100644 index 503f11ef6..000000000 --- a/src/Magnum/Vk/Test/EnumsTest.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - This file is part of Magnum. - - Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, - 2020, 2021 Vladimír Vondruš - - 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 -#include -#include - -#include "Magnum/Mesh.h" -#include "Magnum/PixelFormat.h" -#include "Magnum/Sampler.h" -#include "Magnum/VertexFormat.h" -#include "Magnum/Vk/Enums.h" - -namespace Magnum { namespace Vk { namespace Test { namespace { - -struct EnumsTest: TestSuite::Tester { - explicit EnumsTest(); - - void mapVkFilter(); - void mapVkFilterInvalid(); - - void mapVkSamplerMipmapMode(); - void mapVkSamplerMipmapModeInvalid(); - - void mapVkSamplerAddressMode(); - void mapVkSamplerAddressModeArray(); - void mapVkSamplerAddressModeUnsupported(); - void mapVkSamplerAddressModeInvalid(); -}; - -EnumsTest::EnumsTest() { - addTests({&EnumsTest::mapVkFilter, - &EnumsTest::mapVkFilterInvalid, - - &EnumsTest::mapVkSamplerMipmapMode, - &EnumsTest::mapVkSamplerMipmapModeInvalid, - - &EnumsTest::mapVkSamplerAddressMode, - &EnumsTest::mapVkSamplerAddressModeArray, - &EnumsTest::mapVkSamplerAddressModeUnsupported, - &EnumsTest::mapVkSamplerAddressModeInvalid}); -} - -void EnumsTest::mapVkFilter() { - CORRADE_COMPARE(vkFilter(SamplerFilter::Nearest), VK_FILTER_NEAREST); - CORRADE_COMPARE(vkFilter(SamplerFilter::Linear), VK_FILTER_LINEAR); -} - -void EnumsTest::mapVkFilterInvalid() { - #ifdef CORRADE_NO_ASSERT - CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); - #endif - - std::ostringstream out; - Error redirectError{&out}; - - vkFilter(Magnum::SamplerFilter(0x123)); - CORRADE_COMPARE(out.str(), - "Vk::vkFilter(): invalid filter SamplerFilter(0x123)\n"); -} - -void EnumsTest::mapVkSamplerMipmapMode() { - CORRADE_COMPARE(vkSamplerMipmapMode(SamplerMipmap::Base), VK_SAMPLER_MIPMAP_MODE_NEAREST); /* deliberate */ - CORRADE_COMPARE(vkSamplerMipmapMode(SamplerMipmap::Nearest), VK_SAMPLER_MIPMAP_MODE_NEAREST); - CORRADE_COMPARE(vkSamplerMipmapMode(SamplerMipmap::Linear), VK_SAMPLER_MIPMAP_MODE_LINEAR); -} - -void EnumsTest::mapVkSamplerMipmapModeInvalid() { - #ifdef CORRADE_NO_ASSERT - CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); - #endif - - std::ostringstream out; - Error redirectError{&out}; - - vkSamplerMipmapMode(Magnum::SamplerMipmap(0x123)); - CORRADE_COMPARE(out.str(), - "Vk::vkSamplerMipmapMode(): invalid mode SamplerMipmap(0x123)\n"); -} - -void EnumsTest::mapVkSamplerAddressMode() { - CORRADE_VERIFY(hasVkSamplerAddressMode(SamplerWrapping::Repeat)); - CORRADE_COMPARE(vkSamplerAddressMode(SamplerWrapping::Repeat), VK_SAMPLER_ADDRESS_MODE_REPEAT); - - CORRADE_VERIFY(hasVkSamplerAddressMode(SamplerWrapping::MirroredRepeat)); - CORRADE_COMPARE(vkSamplerAddressMode(SamplerWrapping::MirroredRepeat), VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT); - - CORRADE_VERIFY(hasVkSamplerAddressMode(SamplerWrapping::ClampToEdge)); - CORRADE_COMPARE(vkSamplerAddressMode(SamplerWrapping::ClampToEdge), VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); - - CORRADE_VERIFY(hasVkSamplerAddressMode(SamplerWrapping::ClampToBorder)); - CORRADE_COMPARE(vkSamplerAddressMode(SamplerWrapping::ClampToBorder), VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER); -} - -void EnumsTest::mapVkSamplerAddressModeArray() { - CORRADE_COMPARE(vkSamplerAddressMode<2>({SamplerWrapping::Repeat, SamplerWrapping::ClampToBorder}), (Math::Vector2{VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER})); -} - -void EnumsTest::mapVkSamplerAddressModeUnsupported() { - #ifdef CORRADE_NO_ASSERT - CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); - #endif - - #if 1 - CORRADE_SKIP("All sampler address modes are supported."); - #else - CORRADE_VERIFY(!hasVkSamplerAddressMode(Magnum::SamplerWrapping::MirrorClampToEdge)); - std::ostringstream out; - Error redirectError{&out}; - vkSamplerAddressMode(Magnum::SamplerWrapping::MirrorClampToEdge); - CORRADE_COMPARE(out.str(), - "Vk::vkSamplerAddressMode(): unsupported wrapping SamplerWrapping::MirrorClampToEdge\n"); - #endif -} - -void EnumsTest::mapVkSamplerAddressModeInvalid() { - #ifdef CORRADE_NO_ASSERT - CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); - #endif - - std::ostringstream out; - Error redirectError{&out}; - - vkSamplerAddressMode(Magnum::SamplerWrapping(0x123)); - CORRADE_COMPARE(out.str(), - "Vk::vkSamplerAddressMode(): invalid wrapping SamplerWrapping(0x123)\n"); -} - -}}}} - -CORRADE_TEST_MAIN(Magnum::Vk::Test::EnumsTest) diff --git a/src/Magnum/Vk/Test/SamplerTest.cpp b/src/Magnum/Vk/Test/SamplerTest.cpp new file mode 100644 index 000000000..25c6a9d37 --- /dev/null +++ b/src/Magnum/Vk/Test/SamplerTest.cpp @@ -0,0 +1,289 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 +#include +#include + +#include "Magnum/Sampler.h" +#include "Magnum/Math/Vector3.h" +#include "Magnum/Vk/SamplerCreateInfo.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct SamplerTest: TestSuite::Tester { + explicit SamplerTest(); + + void mapFilter(); + void mapFilterInvalid(); + + void mapMipmap(); + void mapMipmapInvalid(); + + void mapWrapping(); + void mapWrappingVector(); + void mapWrappingInvalid(); + + void createInfoConstruct(); + void createInfoConstructNoInit(); + void createInfoConstructFromVk(); + template void createInfoSetFilter(); + template void createInfoSetMipmap(); + template void createInfoSetWrapping(); + template void createInfoSetWrappingSingleValue(); + + void constructNoCreate(); + void constructCopy(); + + void debugFilter(); + void debugMipmap(); + void debugWrapping(); +}; + +SamplerTest::SamplerTest() { + addTests({&SamplerTest::mapFilter, + &SamplerTest::mapFilterInvalid, + + &SamplerTest::mapMipmap, + &SamplerTest::mapMipmapInvalid, + + &SamplerTest::mapWrapping, + &SamplerTest::mapWrappingVector, + &SamplerTest::mapWrappingInvalid, + + &SamplerTest::createInfoConstruct, + &SamplerTest::createInfoConstructNoInit, + &SamplerTest::createInfoConstructFromVk, + &SamplerTest::createInfoSetFilter, + &SamplerTest::createInfoSetFilter, + &SamplerTest::createInfoSetMipmap, + &SamplerTest::createInfoSetMipmap, + &SamplerTest::createInfoSetWrapping, + &SamplerTest::createInfoSetWrapping, + &SamplerTest::createInfoSetWrappingSingleValue, + &SamplerTest::createInfoSetWrappingSingleValue, + + &SamplerTest::constructNoCreate, + &SamplerTest::constructCopy, + + &SamplerTest::debugFilter, + &SamplerTest::debugMipmap, + &SamplerTest::debugWrapping}); +} + +template struct SamplerTypeTraits; +template<> struct SamplerTypeTraits { + static const char* name() { return "SamplerFilter"; } +}; +template<> struct SamplerTypeTraits { + static const char* name() { return "Magnum::SamplerFilter"; } +}; +template<> struct SamplerTypeTraits { + static const char* name() { return "SamplerMipmap"; } +}; +template<> struct SamplerTypeTraits { + static const char* name() { return "Magnum::SamplerMipmap"; } +}; +template<> struct SamplerTypeTraits { + static const char* name() { return "SamplerWrapping"; } +}; +template<> struct SamplerTypeTraits { + static const char* name() { return "Magnum::SamplerWrapping"; } +}; + +void SamplerTest::mapFilter() { + CORRADE_COMPARE(samplerFilter(Magnum::SamplerFilter::Nearest), SamplerFilter::Nearest); + CORRADE_COMPARE(samplerFilter(Magnum::SamplerFilter::Linear), SamplerFilter::Linear); +} + +void SamplerTest::mapFilterInvalid() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + + samplerFilter(Magnum::SamplerFilter(0x123)); + CORRADE_COMPARE(out.str(), + "Vk::samplerFilter(): invalid filter SamplerFilter(0x123)\n"); +} + +void SamplerTest::mapMipmap() { + CORRADE_COMPARE(samplerMipmap(Magnum::SamplerMipmap::Base), SamplerMipmap::Nearest); /* deliberate */ + CORRADE_COMPARE(samplerMipmap(Magnum::SamplerMipmap::Nearest), SamplerMipmap::Nearest); + CORRADE_COMPARE(samplerMipmap(Magnum::SamplerMipmap::Linear), SamplerMipmap::Linear); +} + +void SamplerTest::mapMipmapInvalid() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + + samplerMipmap(Magnum::SamplerMipmap(0x123)); + CORRADE_COMPARE(out.str(), + "Vk::samplerMipmap(): invalid mode SamplerMipmap(0x123)\n"); +} + +void SamplerTest::mapWrapping() { + CORRADE_COMPARE(samplerWrapping(Magnum::SamplerWrapping::Repeat), SamplerWrapping::Repeat); + + CORRADE_COMPARE(samplerWrapping(Magnum::SamplerWrapping::MirroredRepeat), SamplerWrapping::MirroredRepeat); + + CORRADE_COMPARE(samplerWrapping(Magnum::SamplerWrapping::ClampToEdge), SamplerWrapping::ClampToEdge); + + CORRADE_COMPARE(samplerWrapping(Magnum::SamplerWrapping::ClampToBorder), SamplerWrapping::ClampToBorder); +} + +void SamplerTest::mapWrappingVector() { + CORRADE_COMPARE(samplerWrapping<2>({Magnum::SamplerWrapping::Repeat, Magnum::SamplerWrapping::ClampToBorder}), (Math::Vector2{SamplerWrapping::Repeat, SamplerWrapping::ClampToBorder})); +} + +void SamplerTest::mapWrappingInvalid() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + + samplerWrapping(Magnum::SamplerWrapping(0x123)); + CORRADE_COMPARE(out.str(), + "Vk::samplerWrapping(): invalid wrapping SamplerWrapping(0x123)\n"); +} + +void SamplerTest::createInfoConstruct() { + /** @todo use a real flag once it exists */ + SamplerCreateInfo info{SamplerCreateInfo::Flag(1237)}; + CORRADE_COMPARE(info->flags, 1237); + CORRADE_COMPARE(info->minFilter, VK_FILTER_NEAREST); + CORRADE_COMPARE(info->magFilter, VK_FILTER_NEAREST); + CORRADE_COMPARE(info->mipmapMode, VK_SAMPLER_MIPMAP_MODE_NEAREST); + CORRADE_COMPARE(info->addressModeU, VK_SAMPLER_ADDRESS_MODE_REPEAT); + CORRADE_COMPARE(info->addressModeV, VK_SAMPLER_ADDRESS_MODE_REPEAT); + CORRADE_COMPARE(info->addressModeW, VK_SAMPLER_ADDRESS_MODE_REPEAT); + CORRADE_COMPARE(info->minLod, -1000.0f); + CORRADE_COMPARE(info->maxLod, 1000.0f); +} + +void SamplerTest::createInfoConstructNoInit() { + SamplerCreateInfo info{NoInit}; + info->sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + new(&info) SamplerCreateInfo{NoInit}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); + + CORRADE_VERIFY(std::is_nothrow_constructible::value); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +void SamplerTest::createInfoConstructFromVk() { + VkSamplerCreateInfo vkInfo; + vkInfo.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + + SamplerCreateInfo info{vkInfo}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); +} + +template void SamplerTest::createInfoSetFilter() { + setTestCaseTemplateName(SamplerTypeTraits::name()); + + SamplerCreateInfo info; + info.setMinificationFilter(T::Linear, {}) + .setMagnificationFilter(T::Linear); + CORRADE_COMPARE(info->minFilter, VK_FILTER_LINEAR); + CORRADE_COMPARE(info->mipmapMode, 0); + CORRADE_COMPARE(info->magFilter, VK_FILTER_LINEAR); +} + +template void SamplerTest::createInfoSetMipmap() { + setTestCaseTemplateName(SamplerTypeTraits::name()); + + SamplerCreateInfo info; + info.setMinificationFilter({}, T::Linear); + CORRADE_COMPARE(info->minFilter, 0); + CORRADE_COMPARE(info->mipmapMode, VK_SAMPLER_MIPMAP_MODE_LINEAR); +} + +template void SamplerTest::createInfoSetWrapping() { + setTestCaseTemplateName(SamplerTypeTraits::name()); + + SamplerCreateInfo info; + info.setWrapping({T::MirroredRepeat, T::ClampToEdge, T::MirrorClampToEdge}); + CORRADE_COMPARE(info->addressModeU, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT); + CORRADE_COMPARE(info->addressModeV, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); + CORRADE_COMPARE(info->addressModeW, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE); +} + +template void SamplerTest::createInfoSetWrappingSingleValue() { + setTestCaseTemplateName(SamplerTypeTraits::name()); + + SamplerCreateInfo info; + info.setWrapping(T::ClampToBorder); + CORRADE_COMPARE(info->addressModeU, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER); + CORRADE_COMPARE(info->addressModeV, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER); + CORRADE_COMPARE(info->addressModeW, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER); +} + +void SamplerTest::constructNoCreate() { + { + Sampler sampler{NoCreate}; + CORRADE_VERIFY(!sampler.handle()); + } + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +void SamplerTest::constructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +void SamplerTest::debugFilter() { + std::ostringstream out; + Debug{&out} << SamplerFilter::Linear << SamplerFilter(-10007655); + CORRADE_COMPARE(out.str(), "Vk::SamplerFilter::Linear Vk::SamplerFilter(-10007655)\n"); +} + +void SamplerTest::debugMipmap() { + std::ostringstream out; + Debug{&out} << SamplerMipmap::Linear << SamplerMipmap(-10007655); + CORRADE_COMPARE(out.str(), "Vk::SamplerMipmap::Linear Vk::SamplerMipmap(-10007655)\n"); +} + +void SamplerTest::debugWrapping() { + std::ostringstream out; + Debug{&out} << SamplerWrapping::MirrorClampToEdge << SamplerWrapping(-10007655); + CORRADE_COMPARE(out.str(), "Vk::SamplerWrapping::MirrorClampToEdge Vk::SamplerWrapping(-10007655)\n"); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::SamplerTest) diff --git a/src/Magnum/Vk/Test/SamplerVkTest.cpp b/src/Magnum/Vk/Test/SamplerVkTest.cpp new file mode 100644 index 000000000..c2abac8dd --- /dev/null +++ b/src/Magnum/Vk/Test/SamplerVkTest.cpp @@ -0,0 +1,100 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 + +#include "Magnum/Vk/SamplerCreateInfo.h" +#include "Magnum/Vk/Result.h" +#include "Magnum/Vk/VulkanTester.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct SamplerVkTest: VulkanTester { + explicit SamplerVkTest(); + + void construct(); + void constructMove(); + + void wrap(); +}; + +SamplerVkTest::SamplerVkTest() { + addTests({&SamplerVkTest::construct, + &SamplerVkTest::constructMove, + + &SamplerVkTest::wrap}); +} + +void SamplerVkTest::construct() { + { + Sampler fence{device(), SamplerCreateInfo{} + .setMinificationFilter(SamplerFilter::Linear, SamplerMipmap::Linear) + }; + CORRADE_VERIFY(fence.handle()); + CORRADE_COMPARE(fence.handleFlags(), HandleFlag::DestroyOnDestruction); + } + + /* Shouldn't crash or anything */ + CORRADE_VERIFY(true); +} + +void SamplerVkTest::constructMove() { + Sampler a{device(), SamplerCreateInfo{}}; + VkSampler handle = a.handle(); + + Sampler b = std::move(a); + CORRADE_VERIFY(!a.handle()); + CORRADE_COMPARE(b.handle(), handle); + CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction); + + Sampler c{NoCreate}; + c = std::move(b); + CORRADE_VERIFY(!b.handle()); + CORRADE_COMPARE(b.handleFlags(), HandleFlags{}); + CORRADE_COMPARE(c.handle(), handle); + CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction); + + CORRADE_VERIFY(std::is_nothrow_move_constructible::value); + CORRADE_VERIFY(std::is_nothrow_move_assignable::value); +} + +void SamplerVkTest::wrap() { + VkSampler fence{}; + CORRADE_COMPARE(Result(device()->CreateSampler(device(), + SamplerCreateInfo{}, + nullptr, &fence)), Result::Success); + + auto wrapped = Sampler::wrap(device(), fence, HandleFlag::DestroyOnDestruction); + CORRADE_COMPARE(wrapped.handle(), fence); + + /* Release the handle again, destroy by hand */ + CORRADE_COMPARE(wrapped.release(), fence); + CORRADE_VERIFY(!wrapped.handle()); + device()->DestroySampler(device(), fence, nullptr); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::SamplerVkTest) diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 2d3fc2810..637502163 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -119,6 +119,11 @@ class RenderPassCreateInfo; SubpassDependency are useful only to be passed directly to RenderPassCreateInfo */ enum class Result: Int; +class Sampler; +class SamplerCreateInfo; +enum class SamplerFilter: Int; +enum class SamplerMipmap: Int; +enum class SamplerWrapping: Int; class Shader; class ShaderCreateInfo; class ShaderSet; From a99cde44bbd4e66c16c1f0db842b6b70d4e360ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 8 Mar 2021 17:14:37 +0100 Subject: [PATCH 079/161] Vk: add a ShaderStages enum set. Will be needed by descriptor sets. --- doc/vulkan-mapping.dox | 2 +- src/Magnum/Vk/Shader.h | 14 +++++++++++++- src/Magnum/Vk/Vk.h | 4 ++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index 1ab6265c7..8f4078bc2 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -971,7 +971,7 @@ Vulkan enum | Matching API @type_vk{ShaderFloatControlsIndependence} @m_class{m-label m-flat m-success} **KHR, 1.2** | | @type_vk{ShaderGroupShaderKHR} @m_class{m-label m-flat m-warning} **KHR** | | @type_vk{ShaderModuleCreateFlagBits}, \n @type_vk{ShaderModuleCreateFlags} | @ref ShaderCreateInfo::Flag, \n @ref ShaderCreateInfo::Flags -@type_vk{ShaderStageFlagBits}, \n @type_vk{ShaderStageFlags} | @ref ShaderStage +@type_vk{ShaderStageFlagBits}, \n @type_vk{ShaderStageFlags} | @ref ShaderStage, \n @ref ShaderStages @type_vk{SharingMode} | | @type_vk{SparseImageFormatFlagBits}, \n @type_vk{SparseImageFormatFlags} | | @type_vk{SparseMemoryBindFlagBits}, \n @type_vk{SparseMemoryBindFlags} | | diff --git a/src/Magnum/Vk/Shader.h b/src/Magnum/Vk/Shader.h index a436eba6a..5b0ee47fe 100644 --- a/src/Magnum/Vk/Shader.h +++ b/src/Magnum/Vk/Shader.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Vk::Shader, enum @ref Magnum::Vk::ShaderStage + * @brief Class @ref Magnum::Vk::Shader, enum @ref Magnum::Vk::ShaderStage, enum set @ref Magnum::Vk::ShaderStages * @m_since_latest */ @@ -47,6 +47,7 @@ namespace Implementation { struct DeviceState; } Wraps @type_vk_keyword{ShaderStageFlagBits}. @m_enum_values_as_keywords +@see @ref ShaderStages, @ref ShaderSet::addShader() */ enum class ShaderStage: UnsignedInt { /** Vertex stage */ @@ -113,6 +114,17 @@ enum class ShaderStage: UnsignedInt { RayCallable = VK_SHADER_STAGE_CALLABLE_BIT_KHR }; +/** +@brief Shader stages +@m_since_latest + +Type-safe wrapper for @type_vk_keyword{ShaderStageFlags}. Note that +@cpp ~Vk::ShaderStages{} @ce can be used for @val_vk_keyword{SHADER_STAGE_ALL,ShaderStageFlagBits}. +*/ +typedef Containers::EnumSet ShaderStages; + +CORRADE_ENUMSET_OPERATORS(ShaderStages) + /** @brief Shader @m_since_latest diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 637502163..68495270d 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -129,6 +129,10 @@ class ShaderCreateInfo; class ShaderSet; /* ShaderSpecialization used only directly with ShaderSet */ enum class ShaderStage: UnsignedInt; +/* 0x7FFFFFFF = VK_SHADER_STAGE_ALL, but that would mean including the whole + Vulkan headers. Using a number here and then the actual enum value in + Shadder.h to ensure it doesn't get out of sync. */ +typedef Containers::EnumSet ShaderStages; class SubmitInfo; class SubpassBeginInfo; class SubpassEndInfo; From 052fd5a6834728856a6609df8d82468ebcd04257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 8 Mar 2021 19:44:31 +0100 Subject: [PATCH 080/161] Vk: doc++. Especially relations between {Buffer,Image}Usage, ImageLayout and other APIs. --- src/Magnum/Vk/BufferCreateInfo.h | 23 +++++++++++++++++++---- src/Magnum/Vk/Image.h | 13 +++++++++++++ src/Magnum/Vk/ImageCreateInfo.h | 22 +++++++++++++++++----- src/Magnum/Vk/Mesh.h | 6 ++++-- src/Magnum/Vk/RenderPassCreateInfo.h | 27 ++++++++++++++++----------- 5 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/Magnum/Vk/BufferCreateInfo.h b/src/Magnum/Vk/BufferCreateInfo.h index b97b85668..59e3a277d 100644 --- a/src/Magnum/Vk/BufferCreateInfo.h +++ b/src/Magnum/Vk/BufferCreateInfo.h @@ -49,10 +49,19 @@ Wraps a @type_vk_keyword{BufferUsageFlagBits}. @m_enum_values_as_keywords */ enum class BufferUsage: UnsignedInt { - /** Source of a transfer command */ + /** + * Source of a transfer command. + * @see @ref CommandBuffer::copyBuffer(), + * @ref CommandBuffer::copyBufferToImage() + */ TransferSource = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - /** Destination of a transfer command */ + /** + * Destination of a transfer command. + * @see @ref CommandBuffer::fillBuffer(), + * @ref CommandBuffer::copyBuffer(), + * @ref CommandBuffer::copyImageToBuffer() + */ TransferDestination = VK_BUFFER_USAGE_TRANSFER_DST_BIT, /** Suitable for creating a uniform texel buffer view */ @@ -67,10 +76,16 @@ enum class BufferUsage: UnsignedInt { /** Suitable for a storage buffer */ StorageBuffer = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, - /** Suitable for an index buffer */ + /** + * Suitable for an index buffer. + * @see @ref Mesh::setIndexBuffer() + */ IndexBuffer = VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - /** Suitable for a vertex buffer */ + /** + * Suitable for a vertex buffer. + * @see @ref Mesh::addVertexBuffer() + */ VertexBuffer = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, /** Suitable for a indirect draw buffer */ diff --git a/src/Magnum/Vk/Image.h b/src/Magnum/Vk/Image.h index 23d1a9435..138646647 100644 --- a/src/Magnum/Vk/Image.h +++ b/src/Magnum/Vk/Image.h @@ -47,6 +47,7 @@ namespace Implementation { struct DeviceState; } @brief Image layout @m_since_latest +Wraps @type_vk_keyword{ImageLayout}. @see @ref ImageCreateInfo @m_enum_values_as_keywords */ @@ -97,6 +98,8 @@ enum class ImageLayout: Int { * While this layout will always work, it's recommended to pick a * stricter layout where appropriate, as it may result in better * performance. + * + * @see @ref ImageUsage::Storage */ General = VK_IMAGE_LAYOUT_GENERAL, @@ -109,6 +112,7 @@ enum class ImageLayout: Int { * usable for anything else. * * Only valid for images created with @ref ImageUsage::ColorAttachment. + * @see @ref SubpassDescription::setColorAttachments() */ ColorAttachment = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, @@ -118,6 +122,7 @@ enum class ImageLayout: Int { * * Only valid for images created with * @ref ImageUsage::DepthStencilAttachment. + * @see @ref SubpassDescription::setDepthStencilAttachment() */ DepthStencilAttachment = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, @@ -136,6 +141,8 @@ enum class ImageLayout: Int { * anything else. * * Only valid for images created with @ref ImageUsage::TransferSource. + * @see @ref CommandBuffer::copyImage(), + * @ref CommandBuffer::copyImageToBuffer() */ TransferSource = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, @@ -144,6 +151,12 @@ enum class ImageLayout: Int { * anything else. * * Only valid for images created with @ref ImageUsage::TransferDestination. + * @see @ref CommandBuffer::clearColorImage(), + * @ref CommandBuffer::clearDepthStencilImage(), + * @ref CommandBuffer::clearDepthImage(), + * @ref CommandBuffer::clearStencilImage(), + * @ref CommandBuffer::copyImage(), + * @ref CommandBuffer::copyBufferToImage() */ TransferDestination = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, diff --git a/src/Magnum/Vk/ImageCreateInfo.h b/src/Magnum/Vk/ImageCreateInfo.h index 4a278d0ca..0e0a656a2 100644 --- a/src/Magnum/Vk/ImageCreateInfo.h +++ b/src/Magnum/Vk/ImageCreateInfo.h @@ -58,14 +58,22 @@ enum class ImageUsage: UnsignedInt { /** * Source of a transfer command * - * @see @ref ImageLayout::TransferSource + * @see @ref ImageLayout::TransferSource, + * @ref CommandBuffer::copyImage(), + * @ref CommandBuffer::copyImageToBuffer() */ TransferSource = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, /** * Destination of a transfer command * - * @see @ref ImageLayout::TransferDestination + * @see @ref ImageLayout::TransferDestination, + * @ref CommandBuffer::clearColorImage(), + * @ref CommandBuffer::clearDepthStencilImage(), + * @ref CommandBuffer::clearDepthImage(), + * @ref CommandBuffer::clearStencilImage(), + * @ref CommandBuffer::copyImage(), + * @ref CommandBuffer::copyBufferToImage() */ TransferDestination = VK_IMAGE_USAGE_TRANSFER_DST_BIT, @@ -84,6 +92,7 @@ enum class ImageUsage: UnsignedInt { * Not all pixel formats support shader storage, with some requiring the * @ref DeviceFeature::ShaderStorageImageExtendedFormats feature. See * @ref PixelFormat for more information. + * @see @ref ImageLayout::General */ Storage = VK_IMAGE_USAGE_STORAGE_BIT, @@ -92,7 +101,8 @@ enum class ImageUsage: UnsignedInt { * * Not all pixel formats support color attachment, see @ref PixelFormat for * more information. - * @see @ref ImageLayout::ColorAttachment + * @see @ref ImageLayout::ColorAttachment, + * @ref SubpassDescription::setColorAttachments() */ ColorAttachment = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, @@ -103,7 +113,8 @@ enum class ImageUsage: UnsignedInt { * @ref PixelFormat::Depth32F and @ref PixelFormat::Depth24UnormStencil8UI * / @ref PixelFormat::Depth32FStencil8UI is guaranteed to support * depth/stencil attachment. - * @see @ref ImageLayout::DepthStencilAttachment + * @see @ref ImageLayout::DepthStencilAttachment, + * @ref SubpassDescription::setDepthStencilAttachment() */ DepthStencilAttachment = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, @@ -113,7 +124,8 @@ enum class ImageUsage: UnsignedInt { /** * Input attachment in a shader or framebuffer * - * @see @ref ImageLayout::ShaderReadOnly + * @see @ref ImageLayout::ShaderReadOnly, + * @ref SubpassDescription::setInputAttachments() */ InputAttachment = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT }; diff --git a/src/Magnum/Vk/Mesh.h b/src/Magnum/Vk/Mesh.h index e1e3a30e9..32ffb82dc 100644 --- a/src/Magnum/Vk/Mesh.h +++ b/src/Magnum/Vk/Mesh.h @@ -276,7 +276,8 @@ class MAGNUM_VK_EXPORT Mesh { * @param binding Binding corresponding to a particular * @ref MeshLayout::addBinding() call * @param buffer A @ref Buffer instance or a raw Vulkan buffer - * handle + * handle. Expected to have been created with + * @ref BufferUsage::VertexBuffer. * @param offset Offset into the buffer, in bytes * @return Reference to self (for method chaining) * @@ -297,7 +298,8 @@ class MAGNUM_VK_EXPORT Mesh { /** * @brief Set an index buffer * @param buffer A @ref Buffer instance or a raw Vulkan buffer - * handle + * handle. Expected to have been created with + * @ref BufferUsage::IndexBuffer. * @param offset Offset into the buffer, in bytes * @param indexType Index type * @return Reference to self (for method chaining) diff --git a/src/Magnum/Vk/RenderPassCreateInfo.h b/src/Magnum/Vk/RenderPassCreateInfo.h index 1d26a764e..009dfecbe 100644 --- a/src/Magnum/Vk/RenderPassCreateInfo.h +++ b/src/Magnum/Vk/RenderPassCreateInfo.h @@ -358,9 +358,8 @@ class MAGNUM_VK_EXPORT AttachmentReference { * @brief Constructor * @param attachment Attachment index from the list passed to * @ref RenderPassCreateInfo::setAttachments() - * @param layout Image layout. Should correspond to what's - * passed to @p initialLayout and @p finalLayout in - * @ref AttachmentDescription constructor. + * @param layout Image layout. Should correspond to where the + * reference is used in a @ref SubpassDescription. * * The following @type_vk{AttachmentReference2} fields are pre-filled * in addition to `sType`, everything else is zero-filled: @@ -563,8 +562,10 @@ class MAGNUM_VK_EXPORT SubpassDescription { * Attachments that are being read from in this subpass. The elements * correspond to shader input attachment indices, i.e. a shader input * attachment index @cpp 5 @ce will read from the attachment specified - * at offset @cpp 5 @ce in this list. Use a default-constructed - * @ref AttachmentReference to specify that given input will be unused. + * at offset @cpp 5 @ce in this list. Attachment references should use + * either @ref ImageLayout::General or @ref ImageLayout::ShaderReadOnly; + * use a default-constructed @ref AttachmentReference to specify that + * given input will be unused. */ SubpassDescription& setInputAttachments(Containers::ArrayView attachments) &; /** @overload */ @@ -585,9 +586,11 @@ class MAGNUM_VK_EXPORT SubpassDescription { * * The elements correspond to shader color attachment indices, i.e. a * shader output attachment index @cpp 5 @ce will write from the - * attachment specified at offset @cpp 5 @ce in this list. Use a - * default-constructed @ref AttachmentReference to specify that given - * output will be unused. + * attachment specified at offset @cpp 5 @ce in this list. Attachment + * references should use either @ref ImageLayout::General or + * @ref ImageLayout::ColorAttachment; use a default-constructed + * @ref AttachmentReference to specify that given output will be + * unused. */ #ifdef DOXYGEN_GENERATING_OUTPUT SubpassDescription& setColorAttachments(Containers::ArrayView attachments, Containers::ArrayView resolveAttachments = {}) &; @@ -610,9 +613,11 @@ class MAGNUM_VK_EXPORT SubpassDescription { * @return Reference to self (for method chaining) * * Depth/stencil attachment that is being written to in this subpass. - * Calling this function with a default-constructed - * @ref AttachmentReference is equivalent to not calling it at all, and - * both mean there's no depth/stencil attachment. + * The attachment reference should use either @ref ImageLayout::General + * or @ref ImageLayout::DepthStencilAttachment; calling this function + * with a default-constructed @ref AttachmentReference is equivalent to + * not calling it at all, and both mean there's no depth/stencil + * attachment. */ SubpassDescription& setDepthStencilAttachment(AttachmentReference attachment) &; /** @overload */ From 2bf014f1e66af27184260bfce50bef346a1ba8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 8 Mar 2021 22:07:30 +0100 Subject: [PATCH 081/161] Vk: document also what CreateInfo setters do to the underlying struct. --- doc/developers.dox | 5 ++ src/Magnum/Vk/DeviceCreateInfo.h | 39 +++++++++++++-- src/Magnum/Vk/InstanceCreateInfo.h | 25 ++++++++++ .../Vk/RasterizationPipelineCreateInfo.h | 8 ++-- src/Magnum/Vk/RenderPassCreateInfo.h | 48 ++++++++++++++++++- 5 files changed, 116 insertions(+), 9 deletions(-) diff --git a/doc/developers.dox b/doc/developers.dox index 7e1985c64..bebabdf9e 100644 --- a/doc/developers.dox +++ b/doc/developers.dox @@ -792,6 +792,11 @@ unless it doesn't affect public API at all. - The main constructor(s) should explicitly list what structure fields are filled to which value, and if the constructor isn't enough to get a working state, it should also clearly mention what needs to be done next +- For everything non-essential or what isn't practical to be set in + constructor a setter should be added. If applicable, document what + subsequent calls to the same function result in (for example when a list + gets cleared while all other functions append to lists). The docs should + again list what underlying structure fields are set to which value. - Every class should have a @ref NoInitT constructor, which keeps the structure uninitialized and *doesn't* allocate any internal state - Every class should have a constructor taking the underlying Vulkan diff --git a/src/Magnum/Vk/DeviceCreateInfo.h b/src/Magnum/Vk/DeviceCreateInfo.h index 088a5ad14..6a73d3a73 100644 --- a/src/Magnum/Vk/DeviceCreateInfo.h +++ b/src/Magnum/Vk/DeviceCreateInfo.h @@ -175,10 +175,18 @@ class MAGNUM_VK_EXPORT DeviceCreateInfo { * All listed extensions are expected to be supported either globally * or in at least one of the enabled layers, use * @ref ExtensionProperties::isSupported() to check for their presence. - * * The function makes copies of string views that are not global or * null-terminated, use the @link Containers::Literals::operator""_s() @endlink * literal to prevent that where possible. + * + * The following @type_vk{DeviceCreateInfo} fields are set by this + * function: + * + * - `enabledExtensionCount` to the count of extensions added + * previously by this function plus @cpp extensions.size() @ce + * - `pEnabledExtensionNames` to an array containing all extension + * strings added previously by this function together with ones + * from @p extensions */ DeviceCreateInfo& addEnabledExtensions(Containers::ArrayView extensions) &; /** @overload */ @@ -215,8 +223,13 @@ class MAGNUM_VK_EXPORT DeviceCreateInfo { * corresponding extension enabled via @ref addEnabledExtensions(). Use * @ref DeviceProperties::features() to check for feature support. * - * Depending on what features are enabled, a subset of the following - * structures will be added to the `pNext` chain: + * If Vulkan 1.1 is not supported and + * @vk_extension{KHR,get_physical_device_properties2} is not enabled on + * the instance, the `pEnabledFeatures` field in + * @type_vk{DeviceCreateInfo} is set to the Vulkan 1.0 subset of + * @p features. Otherwise, depending on what features are enabled, a + * subset of the following structures will be added to the `pNext` + * chain: * * - @type_vk_keyword{PhysicalDeviceProtectedMemoryFeatures} (Vulkan * 1.1) @@ -292,6 +305,16 @@ class MAGNUM_VK_EXPORT DeviceCreateInfo { * @return Reference to self (for method chaining) * * At least one queue has to be added. + * + * The following @type_vk{DeviceCreateInfo} fields are set by this + * function: + * + * - `queueCreateInfoCount` to the count of queues added previously + * by this function plus @cpp queues.size() @ce + * - `pQueueCreateInfos` to an array containing all queue create + * infos added previously by this function together with ones + * from @p family and @p priorities + * * @see @ref DeviceProperties::pickQueueFamily() * @todoc link to addQueues(QueueFlags) once doxygen finally GROWS UP * and can link to &-qualified functions FFS @@ -331,8 +354,16 @@ class MAGNUM_VK_EXPORT DeviceCreateInfo { * @return Reference to self (for method chaining) * * Compared to @ref addQueues() this allows you to specify additional - * queue properties using the `pNext` chain. The info is uses as-is, + * queue properties using the `pNext` chain. The info is used as-is, * with all pointers expected to stay in scope until device creation. + * + * The following @type_vk{DeviceCreateInfo} fields are set by this + * function: + * + * - `queueCreateInfoCount` to the count of queues added previously + * by this function plus @cpp 1 @ce + * - `pQueueCreateInfos` to an array containing all queue create + * infos added previously by this function together with @p info */ DeviceCreateInfo& addQueues(const VkDeviceQueueCreateInfo& info) &; /** @overload */ diff --git a/src/Magnum/Vk/InstanceCreateInfo.h b/src/Magnum/Vk/InstanceCreateInfo.h index 24f91a1bf..08b6b17d0 100644 --- a/src/Magnum/Vk/InstanceCreateInfo.h +++ b/src/Magnum/Vk/InstanceCreateInfo.h @@ -159,6 +159,13 @@ class MAGNUM_VK_EXPORT InstanceCreateInfo { * The function makes copies of string views that are not global or * null-terminated, use the @link Containers::Literals::operator""_s() @endlink * literal to prevent that where possible. + * + * The following @type_vk{InstanceCreateInfo} fields are set by this + * function: + * + * - `pApplicationInfo` + * - @cpp pApplicationInfo->pApplicationName @ce to @p name + * - @cpp pApplicationInfo->applicationVersion @ce to @p version */ InstanceCreateInfo& setApplicationInfo(Containers::StringView name, Version version); @@ -175,6 +182,15 @@ class MAGNUM_VK_EXPORT InstanceCreateInfo { * The function makes copies of string views that are not global or * null-terminated, use the @link Containers::Literals::operator""_s() @endlink * literal to prevent that where possible. + * + * The following @type_vk{InstanceCreateInfo} fields are set by this + * function: + * + * - `enabledLayerCount` to the count of layers added previously by + * this function plus @cpp layers.size() @ce + * - `pEnabledLayerNames` to an array containing all layer strings + * added previously by this function together with ones from + * @p layers */ InstanceCreateInfo& addEnabledLayers(Containers::ArrayView layers); /** @overload */ @@ -195,6 +211,15 @@ class MAGNUM_VK_EXPORT InstanceCreateInfo { * The function makes copies of string views that are not global or * null-terminated, use the @link Containers::Literals::operator""_s() @endlink * literal to prevent that where possible. + * + * The following @type_vk{InstanceCreateInfo} fields are set by this + * function: + * + * - `enabledExtensionCount` to the count of extensions added + * previously by this function plus @cpp extensions.size() @ce + * - `pEnabledExtensionNames` to an array containing all extension + * strings added previously by this function together with ones + * from @p extensions */ InstanceCreateInfo& addEnabledExtensions(Containers::ArrayView extensions); /** @overload */ diff --git a/src/Magnum/Vk/RasterizationPipelineCreateInfo.h b/src/Magnum/Vk/RasterizationPipelineCreateInfo.h index 34ce4ddbf..0052641be 100644 --- a/src/Magnum/Vk/RasterizationPipelineCreateInfo.h +++ b/src/Magnum/Vk/RasterizationPipelineCreateInfo.h @@ -454,8 +454,8 @@ class MAGNUM_VK_EXPORT RasterizationPipelineCreateInfo { * @f$ [0.0, 1.0] @f$. * * The following @type_vk{GraphicsPipelineCreateInfo} and substructure - * fields are modified, in addition to `sType` of newly referenced - * structures: + * fields are modified by this function, in addition to `sType` of + * newly referenced structures: * * - `pViewportState` * - @cpp pViewportState->viewportCount @ce to @cpp 1 @ce @@ -501,8 +501,8 @@ class MAGNUM_VK_EXPORT RasterizationPipelineCreateInfo { * @brief Set dynamic states * * The following @type_vk{GraphicsPipelineCreateInfo} and substructure - * fields are modified, in addition to `sType` of newly referenced - * structures: + * fields are modified by this function, in addition to `sType` of + * newly referenced structures: * * - `pDynamicState` * - @cpp pDynamicState->dynamicStateCount @ce to count of values diff --git a/src/Magnum/Vk/RenderPassCreateInfo.h b/src/Magnum/Vk/RenderPassCreateInfo.h index 009dfecbe..32df3f362 100644 --- a/src/Magnum/Vk/RenderPassCreateInfo.h +++ b/src/Magnum/Vk/RenderPassCreateInfo.h @@ -566,6 +566,12 @@ class MAGNUM_VK_EXPORT SubpassDescription { * either @ref ImageLayout::General or @ref ImageLayout::ShaderReadOnly; * use a default-constructed @ref AttachmentReference to specify that * given input will be unused. + * + * The following @type_vk{SubpassDescription2} fields are set by this + * function: + * + * - `inputAttachmentCount` to @cpp attachments.size() @ce + * - `pInputAttachments` to a copy of @p attachments */ SubpassDescription& setInputAttachments(Containers::ArrayView attachments) &; /** @overload */ @@ -591,6 +597,14 @@ class MAGNUM_VK_EXPORT SubpassDescription { * @ref ImageLayout::ColorAttachment; use a default-constructed * @ref AttachmentReference to specify that given output will be * unused. + * + * The following @type_vk{SubpassDescription2} fields are set by this + * function: + * + * - `colorAttachmentCount` to @cpp attachments.size() @ce + * - `pColorAttachments` to a copy of @p attachments + * - `pResolveAttachments` to a copy of @p resolveAttachments, if + * the parameter is non-empty */ #ifdef DOXYGEN_GENERATING_OUTPUT SubpassDescription& setColorAttachments(Containers::ArrayView attachments, Containers::ArrayView resolveAttachments = {}) &; @@ -618,6 +632,11 @@ class MAGNUM_VK_EXPORT SubpassDescription { * with a default-constructed @ref AttachmentReference is equivalent to * not calling it at all, and both mean there's no depth/stencil * attachment. + * + * The following @type_vk{SubpassDescription2} fields are set by this + * function: + * + * - `pDepthStencilAttachment` to a copy of @p attachment */ SubpassDescription& setDepthStencilAttachment(AttachmentReference attachment) &; /** @overload */ @@ -631,6 +650,11 @@ class MAGNUM_VK_EXPORT SubpassDescription { * be preserved throughout the subpass. The @p attachment values are * indices into the list passed to * @ref RenderPassCreateInfo::setAttachments(). + * + * The following @type_vk{SubpassDescription2} fields are set by this + * function: + * + * - `pPreserveAttachments` to a copy of @p attachments */ SubpassDescription& setPreserveAttachments(Containers::ArrayView attachments) &; /** @overload */ @@ -966,6 +990,12 @@ class MAGNUM_VK_EXPORT RenderPassCreateInfo { * * Subsequent calls to this function will *replace* the previous set, * not append to it. + * + * The following @type_vk{RenderPassCreateInfo2} fields are set by this + * function: + * + * - `attachmentCount` to @cpp attachments.size() @ce + * - `pAttachments` to a copy of @p attachments */ RenderPassCreateInfo& setAttachments(Containers::ArrayView attachments); /** @overload */ @@ -984,6 +1014,16 @@ class MAGNUM_VK_EXPORT RenderPassCreateInfo { * to nested allocations inside @ref SubpassDescription, it's more * efficient to *move* the instances one by one than having to * deep-copy a list. + * + * The following @type_vk{RenderPassCreateInfo2} fields are set by this + * function: + * + * - `subpassCount` to the count of subpasses added previously by + * this function plus @cpp 1 @ce + * - `pSubpasses` to an array containing all subpass descriptions + * added previously by this function together with @p subpass; + * ownership of associated @ref SubpassDescription state is moved + * to the @ref RenderPassCreateInfo instance */ RenderPassCreateInfo& addSubpass(SubpassDescription&& subpass); @@ -991,8 +1031,14 @@ class MAGNUM_VK_EXPORT RenderPassCreateInfo { * @brief Set subpass dependencies * @return Reference to self (for method chaining) * - * ubsequent calls to this function will *replace* the previous set, + * Subsequent calls to this function will *replace* the previous set, * not append to it. + * + * The following @type_vk{RenderPassCreateInfo2} fields are set by this + * function: + * + * - `dependencyCount` to @cpp dependencies.size() @ce + * - `pDependencies` to a copy of @p dependencies */ RenderPassCreateInfo& setDependencies(Containers::ArrayView dependencies); /** @overload */ From 391e680721172cd0328125f0473a430c7b6aeff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 11 Mar 2021 10:44:52 +0100 Subject: [PATCH 082/161] Vk: implement a DescriptorSetLayout. Together with DescriptorBindingFlags, because it affects the design in a rather specific way and it wouldn't make sense to postpone this and forget all again until it becomes needed. --- doc/snippets/MagnumVk.cpp | 50 ++ doc/vulkan-mapping.dox | 17 +- doc/vulkan-support.dox | 2 +- src/Magnum/Vk/BufferCreateInfo.h | 20 +- src/Magnum/Vk/CMakeLists.txt | 3 + src/Magnum/Vk/DescriptorSetLayout.cpp | 216 ++++++++ src/Magnum/Vk/DescriptorSetLayout.h | 176 +++++++ src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h | 480 ++++++++++++++++++ src/Magnum/Vk/DeviceFeatures.h | 44 +- src/Magnum/Vk/Image.h | 3 + src/Magnum/Vk/ImageCreateInfo.h | 7 +- src/Magnum/Vk/Test/CMakeLists.txt | 4 + .../Vk/Test/DescriptorSetLayoutTest.cpp | 320 ++++++++++++ .../Vk/Test/DescriptorSetLayoutVkTest.cpp | 104 ++++ src/Magnum/Vk/Vk.h | 3 + 15 files changed, 1419 insertions(+), 30 deletions(-) create mode 100644 src/Magnum/Vk/DescriptorSetLayout.cpp create mode 100644 src/Magnum/Vk/DescriptorSetLayout.h create mode 100644 src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h create mode 100644 src/Magnum/Vk/Test/DescriptorSetLayoutTest.cpp create mode 100644 src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index 06277b312..30bbdc89f 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -39,6 +39,7 @@ #include "Magnum/Vk/CommandBuffer.h" #include "Magnum/Vk/CommandPoolCreateInfo.h" #include "Magnum/Vk/ComputePipelineCreateInfo.h" +#include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" #include "Magnum/Vk/DeviceCreateInfo.h" #include "Magnum/Vk/DeviceFeatures.h" #include "Magnum/Vk/DeviceProperties.h" @@ -312,6 +313,55 @@ fence.wait(); /* [CommandBuffer-usage-submit] */ } +{ +Vk::Device device{NoCreate}; +/* The include should be a no-op here since it was already included above */ +/* [DescriptorSetLayout-creation] */ +#include + +DOXYGEN_IGNORE() + +Vk::DescriptorSetLayout layout{device, Vk::DescriptorSetLayoutCreateInfo{ + {{0, Vk::DescriptorType::UniformBuffer}}, + {{1, Vk::DescriptorType::CombinedImageSampler, 1, + Vk::ShaderStage::Fragment}} +}}; +/* [DescriptorSetLayout-creation] */ +} + +{ +Vk::Device device{NoCreate}; +/* [DescriptorSetLayout-creation-immutable-samplers] */ +Vk::Sampler sampler{DOXYGEN_IGNORE(NoCreate)}; + +Vk::DescriptorSetLayout layout{device, Vk::DescriptorSetLayoutCreateInfo{ + {{0, Vk::DescriptorType::UniformBuffer}}, + {{1, Vk::DescriptorType::CombinedImageSampler, {sampler}, + Vk::ShaderStage::Fragment}} +}}; +/* [DescriptorSetLayout-creation-immutable-samplers] */ +} + +{ +Vk::Instance instance{NoCreate}; +/* [DescriptorSetLayout-creation-binding-flags] */ +Vk::Device device{instance, Vk::DeviceCreateInfo{DOXYGEN_IGNORE(Vk::pickDevice(instance))} + DOXYGEN_IGNORE() + .setEnabledFeatures( + Vk::DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind| + DOXYGEN_IGNORE(Vk::DeviceFeatures{}) + ) +}; + +Vk::DescriptorSetLayout layout{device, Vk::DescriptorSetLayoutCreateInfo{ + {{0, Vk::DescriptorType::UniformBuffer, 1, + ~Vk::ShaderStages{}, + Vk::DescriptorSetLayoutBinding::Flag::UpdateAfterBind}}, + DOXYGEN_IGNORE() +}}; +/* [DescriptorSetLayout-creation-binding-flags] */ +} + { Vk::Instance instance; /* The include should be a no-op here since it was already included above */ diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index 8f4078bc2..55dde6ffb 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -60,7 +60,7 @@ Vulkan handle | Matching API @type_vk{DebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DescriptorPool} | | @type_vk{DescriptorSet} | | -@type_vk{DescriptorSetLayout} | | +@type_vk{DescriptorSetLayout} | @ref DescriptorSetLayout @type_vk{DescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{Device} | @ref Device @type_vk{DeviceMemory} | @ref Memory @@ -191,7 +191,7 @@ Vulkan function | Matching API @fn_vk{CreateDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | | @fn_vk{CreateDeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR**, \n @fn_vk{DestroyDeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR** | | @fn_vk{CreateDescriptorPool}, \n @fn_vk{DestroyDescriptorPool} | | -@fn_vk{CreateDescriptorSetLayout}, \n @fn_vk{DestroyDescriptorSetLayout} | | +@fn_vk{CreateDescriptorSetLayout}, \n @fn_vk{DestroyDescriptorSetLayout} | @ref DescriptorSetLayout constructor and destructor @fn_vk{CreateDescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1**, \n @fn_vk{DestroyDescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{CreateDevice}, \n @fn_vk{DestroyDevice} | @ref Device constructor and destructor @fn_vk{CreateEvent}, \n @fn_vk{DestroyEvent} | | @@ -466,10 +466,9 @@ Vulkan structure | Matching API @type_vk{DescriptorPoolCreateInfo} | | @type_vk{DescriptorPoolSize} | | @type_vk{DescriptorSetAllocateInfo} | | -@type_vk{DescriptorSetLayoutBinding} | | -@type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} | | -@type_vk{DescriptorSetLayoutCreateInfo} | | -@type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | | +@type_vk{DescriptorSetLayoutBinding} | @ref DescriptorSetLayoutBinding +@type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} @m_class{m-label m-flqat m-success} **EXT, 1.2** | @ref DescriptorSetLayoutCreateInfo +@type_vk{DescriptorSetLayoutCreateInfo} | @ref DescriptorSetLayoutCreateInfo @type_vk{DescriptorSetLayoutSupport} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorSetVariableDescriptorCountAllocateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{DescriptorSetVariableDescriptorCountLayoutSupport} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @@ -826,11 +825,11 @@ Vulkan enum | Matching API @type_vk{DebugReportObjectTypeEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DebugUtilsMessageSeverityFlagBitsEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @type_vk{DebugUtilsMessageTypeFlagsEXT} @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DependencyFlagBits}, \n @type_vk{DependencyFlags} | @ref DependencyFlag, \n @ref DependencyFlags -@type_vk{DescriptorBindingFlagBits} @m_class{m-label m-flat m-success} **EXT, 1.2**, \n @type_vk{DescriptorBindingFlags} @m_class{m-label m-flat m-success} **EXT, 1.2** | | +@type_vk{DescriptorBindingFlagBits} @m_class{m-label m-flat m-success} **EXT, 1.2**, \n @type_vk{DescriptorBindingFlags} @m_class{m-label m-flat m-success} **EXT, 1.2** | @ref DescriptorSetLayoutBinding::Flag, \n @ref DescriptorSetLayoutBinding::Flags @type_vk{DescriptorPoolCreateFlagBits}, \n @type_vk{DescriptorPoolCreateFlags} | | -@type_vk{DescriptorSetLayoutCreateFlagBits}, \n @type_vk{DescriptorSetLayoutCreateFlags} | | +@type_vk{DescriptorSetLayoutCreateFlagBits}, \n @type_vk{DescriptorSetLayoutCreateFlags} | @ref DescriptorSetLayoutCreateInfo::Flag, \n @ref DescriptorSetLayoutCreateInfo::Flags @type_vk{DescriptorUpdateTemplateType} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@type_vk{DescriptorType} | | +@type_vk{DescriptorType} | @ref DescriptorType @type_vk{DeviceQueueCreateFlagBits}, \n @type_vk{DeviceQueueCreateFlags} | | @type_vk{DriverId} @m_class{m-label m-flat m-success} **KHR, 1.2** | @ref DeviceDriver @type_vk{DynamicState} | @ref DynamicRasterizationState diff --git a/doc/vulkan-support.dox b/doc/vulkan-support.dox index 9791802f3..ce90aeae7 100644 --- a/doc/vulkan-support.dox +++ b/doc/vulkan-support.dox @@ -90,7 +90,7 @@ Extension | Status @vk_extension{KHR,create_renderpass2} | done @vk_extension{EXT,sampler_filter_minmax} | | @vk_extension{KHR,image_format_list} | | -@vk_extension{EXT,descriptor_indexing} | | +@vk_extension{EXT,descriptor_indexing} | done except properties and variable descriptor count allocation @vk_extension{EXT,shader_viewport_index_layer} | | @vk_extension{KHR,draw_indirect_count} | | @vk_extension{KHR,shader_subgroup_extended_types} | | diff --git a/src/Magnum/Vk/BufferCreateInfo.h b/src/Magnum/Vk/BufferCreateInfo.h index 59e3a277d..8fb6b0055 100644 --- a/src/Magnum/Vk/BufferCreateInfo.h +++ b/src/Magnum/Vk/BufferCreateInfo.h @@ -64,16 +64,28 @@ enum class BufferUsage: UnsignedInt { */ TransferDestination = VK_BUFFER_USAGE_TRANSFER_DST_BIT, - /** Suitable for creating a uniform texel buffer view */ + /** + * Suitable for creating a uniform texel buffer view. + * @see @ref DescriptorType::UniformTexelBuffer + */ UniformTexelBuffer = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, - /** Suitable for creating a storage texel buffer view */ + /** + * Suitable for creating a storage texel buffer view. + * @see @ref DescriptorType::StorageTexelBuffer + */ StorageTexelBuffer = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT, - /** Suitable for a uniform buffer */ + /** + * Suitable for a uniform buffer. + * @see @ref DescriptorType::UniformBuffer + */ UniformBuffer = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - /** Suitable for a storage buffer */ + /** + * Suitable for a storage buffer. + * @see @ref DescriptorType::StorageBuffer + */ StorageBuffer = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, /** diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 7a2a08b57..fcebd1574 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -29,6 +29,7 @@ find_package(Vulkan REQUIRED) set(MagnumVk_SRCS CommandBuffer.cpp CommandPool.cpp + DescriptorSetLayout.cpp Extensions.cpp Fence.cpp Framebuffer.cpp @@ -72,6 +73,8 @@ set(MagnumVk_HEADERS CommandPool.h CommandPoolCreateInfo.h ComputePipelineCreateInfo.h + DescriptorSetLayout.h + DescriptorSetLayoutCreateInfo.h Device.h DeviceCreateInfo.h DeviceFeatures.h diff --git a/src/Magnum/Vk/DescriptorSetLayout.cpp b/src/Magnum/Vk/DescriptorSetLayout.cpp new file mode 100644 index 000000000..6e0858432 --- /dev/null +++ b/src/Magnum/Vk/DescriptorSetLayout.cpp @@ -0,0 +1,216 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 "DescriptorSetLayout.h" +#include "DescriptorSetLayoutCreateInfo.h" + +#include +#include +#include + +#include "Magnum/Vk/Assert.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/Result.h" + +namespace Magnum { namespace Vk { + +DescriptorSetLayoutBinding::DescriptorSetLayoutBinding(const UnsignedInt binding, const DescriptorType descriptorType, const UnsignedInt descriptorCount, const ShaderStages stages, Flags flags): _binding{}, _flags{VkDescriptorBindingFlags(flags)} { + _binding.binding = binding; + _binding.descriptorType = VkDescriptorType(descriptorType); + _binding.descriptorCount = descriptorCount; + _binding.stageFlags = VkShaderStageFlags(stages); +} + +DescriptorSetLayoutBinding::DescriptorSetLayoutBinding(const UnsignedInt binding, const DescriptorType descriptorType, const Containers::ArrayView immutableSamplers, const ShaderStages stages, Flags flags): _binding{}, _flags{VkDescriptorBindingFlags(flags)} { + Containers::ArrayView immutableSamplersCopy; + _data = Containers::ArrayTuple{ + {Containers::NoInit, immutableSamplers.size(), immutableSamplersCopy} + }; + Utility::copy(immutableSamplers, immutableSamplersCopy); + + _binding.binding = binding; + _binding.descriptorType = VkDescriptorType(descriptorType); + _binding.descriptorCount = immutableSamplers.size(); + _binding.pImmutableSamplers = immutableSamplersCopy; + _binding.stageFlags = VkShaderStageFlags(stages); +} + +DescriptorSetLayoutBinding::DescriptorSetLayoutBinding(const UnsignedInt binding, const DescriptorType descriptorType, const std::initializer_list immutableSamplers, const ShaderStages stages, Flags flags): DescriptorSetLayoutBinding{binding, descriptorType, Containers::arrayView(immutableSamplers), stages, flags} {} + +DescriptorSetLayoutBinding::DescriptorSetLayoutBinding(NoInitT) noexcept {} + +DescriptorSetLayoutBinding::DescriptorSetLayoutBinding(const VkDescriptorSetLayoutBinding& binding, const VkDescriptorBindingFlags flags): + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _binding(binding), + _flags{flags} {} + +DescriptorSetLayoutBinding::DescriptorSetLayoutBinding(DescriptorSetLayoutBinding&& other) noexcept: + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _binding(other._binding), + _data{std::move(other._data)}, + _flags{other._flags} +{ + /* Ensure the previous instance doesn't reference state that's now ours */ + /** @todo this is now more like a destructible move, do it more selectively + and clear only what's really ours and not external? */ + other._binding.pImmutableSamplers = nullptr; +} + +DescriptorSetLayoutBinding::~DescriptorSetLayoutBinding() = default; + +DescriptorSetLayoutBinding& DescriptorSetLayoutBinding::operator=(DescriptorSetLayoutBinding&& other) noexcept { + using std::swap; + swap(other._binding, _binding); + swap(other._data, _data); + swap(other._flags, _flags); + return *this; +} + +DescriptorSetLayoutCreateInfo::DescriptorSetLayoutCreateInfo(const Containers::ArrayView> bindings, const Flags flags): _info{} { + /* Check the total count of immutable samplers to allocate them all in a + contiguous memory location. Also check if we have any binding flags. If + yes, we have to create an additional array and put a structure into the + pNext chain. */ + std::size_t immutableSamplerCount = 0; + bool hasBindingFlags = false; + for(const DescriptorSetLayoutBinding& b: bindings) { + if(b->pImmutableSamplers) immutableSamplerCount += b->descriptorCount; + if(b.flags()) hasBindingFlags = true; + } + + /* Allocate a single block of memory for everything. (I'm still amazed at + how simple this is and yet how useful.) */ + Containers::ArrayView bindingsCopy; + Containers::ArrayView bindingFlagsCopy; + Containers::ArrayView bindingsCreateInfoView; + Containers::ArrayView immutableSamplersCopy; + _data = Containers::ArrayTuple{ + {Containers::NoInit, bindings.size(), bindingsCopy}, + {Containers::NoInit, hasBindingFlags ? bindings.size() : 0, bindingFlagsCopy}, + {Containers::ValueInit, hasBindingFlags ? 1u : 0u, bindingsCreateInfoView}, + {Containers::NoInit, immutableSamplerCount, immutableSamplersCopy} + }; + + /* Copy the binding and then for each manually copy and reroute the + immutable samplers, if any; copy the flags as well if there are any */ + std::size_t immutableSamplerOffset = 0; + for(std::size_t i = 0; i != bindings.size(); ++i) { + const DescriptorSetLayoutBinding& b = bindings[i]; + bindingsCopy[i] = b; + if(b->pImmutableSamplers) { + Utility::copy( + {b->pImmutableSamplers, b->descriptorCount}, + immutableSamplersCopy.slice(immutableSamplerOffset, immutableSamplerOffset + b->descriptorCount)); + bindingsCopy[i].pImmutableSamplers = immutableSamplersCopy + immutableSamplerOffset; + immutableSamplerOffset += b->descriptorCount; + } + if(hasBindingFlags) bindingFlagsCopy[i] = b.flags(); + } + CORRADE_INTERNAL_ASSERT(immutableSamplerOffset == immutableSamplerCount); + + _info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + _info.flags = VkDescriptorSetLayoutCreateFlags(flags); + _info.bindingCount = bindings.size(); + _info.pBindings = bindingsCopy; + if(hasBindingFlags) { + bindingsCreateInfoView[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO; + bindingsCreateInfoView[0].bindingCount = bindings.size(); + bindingsCreateInfoView[0].pBindingFlags = bindingFlagsCopy; + _info.pNext = bindingsCreateInfoView; + } +} + +DescriptorSetLayoutCreateInfo::DescriptorSetLayoutCreateInfo(const std::initializer_list> bindings, const Flags flags): DescriptorSetLayoutCreateInfo{Containers::arrayView(bindings), flags} {} + +DescriptorSetLayoutCreateInfo::DescriptorSetLayoutCreateInfo(NoInitT) noexcept {} + +DescriptorSetLayoutCreateInfo::DescriptorSetLayoutCreateInfo(const VkDescriptorSetLayoutCreateInfo& info): + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _info(info) {} + +DescriptorSetLayoutCreateInfo::DescriptorSetLayoutCreateInfo(DescriptorSetLayoutCreateInfo&& other) noexcept: + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _info(other._info), + _data{std::move(other._data)} +{ + /* Ensure the previous instance doesn't reference state that's now ours */ + /** @todo this is now more like a destructible move, do it more selectively + and clear only what's really ours and not external? */ + other._info.pNext = nullptr; + other._info.bindingCount = 0; + other._info.pBindings = nullptr; +} + +DescriptorSetLayoutCreateInfo::~DescriptorSetLayoutCreateInfo() = default; + +DescriptorSetLayoutCreateInfo& DescriptorSetLayoutCreateInfo::operator=(DescriptorSetLayoutCreateInfo&& other) noexcept { + using std::swap; + swap(other._info, _info); + swap(other._data, _data); + return *this; +} + +DescriptorSetLayout DescriptorSetLayout::wrap(Device& device, const VkDescriptorSetLayout handle, const HandleFlags flags) { + DescriptorSetLayout out{NoCreate}; + out._device = &device; + out._handle = handle; + out._flags = flags; + return out; +} + +DescriptorSetLayout::DescriptorSetLayout(Device& device, const DescriptorSetLayoutCreateInfo& info): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} { + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateDescriptorSetLayout(device, info, nullptr, &_handle)); +} + +DescriptorSetLayout::DescriptorSetLayout(NoCreateT): _device{}, _handle{} {} + +DescriptorSetLayout::DescriptorSetLayout(DescriptorSetLayout&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} { + other._handle = {}; +} + +DescriptorSetLayout::~DescriptorSetLayout() { + if(_handle && (_flags & HandleFlag::DestroyOnDestruction)) + (**_device).DestroyDescriptorSetLayout(*_device, _handle, nullptr); +} + +DescriptorSetLayout& DescriptorSetLayout::operator=(DescriptorSetLayout&& other) noexcept { + using std::swap; + swap(other._device, _device); + swap(other._handle, _handle); + swap(other._flags, _flags); + return *this; +} + +VkDescriptorSetLayout DescriptorSetLayout::release() { + const VkDescriptorSetLayout handle = _handle; + _handle = {}; + return handle; +} + +}} diff --git a/src/Magnum/Vk/DescriptorSetLayout.h b/src/Magnum/Vk/DescriptorSetLayout.h new file mode 100644 index 000000000..1e4c4167b --- /dev/null +++ b/src/Magnum/Vk/DescriptorSetLayout.h @@ -0,0 +1,176 @@ +#ifndef Magnum_Vk_DescriptorSetLayout_h +#define Magnum_Vk_DescriptorSetLayout_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Vk::DescriptorSetLayout + * @m_since_latest + */ + +#include "Magnum/Tags.h" +#include "Magnum/Vk/Handle.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Descriptor set layout +@m_since_latest + +Wraps a @type_vk_keyword{DescriptorSetLayout}. A descriptor set layout lists +descriptors (such as uniform buffers or samplers) used by shaders in a +@ref Pipeline. + +@section Vk-DescriptorSetLayout-creation Descriptor set layout creation + +The @ref DescriptorSetLayoutCreateInfo class takes one or more +@ref DescriptorSetLayoutBinding entries, where each specifies the binding +number, descriptor type, descriptor count in case of descriptor arrays and +which shader stages are designed to access the binding. In the following +example one uniform buffer binding @cpp 0 @ce is accessible by any stages and +one combined image/sampler binding @cpp 1 @ce is accessed only by +@link ShaderStage::Fragment @endlink: + +@snippet MagnumVk.cpp DescriptorSetLayout-creation + + + +@m_class{m-note m-info} + +@par + Note that in C++11 you have to use double brackets (@cpp {{ }} @ce) to + initialize the @ref DescriptorSetLayoutBinding entries, as shown above. + With C++14 and newer it should work with just a single pair of brackets. + +@subsection Vk-DescriptorSetLayout-creation-immutable-samplers Immutable samplers + +For @ref DescriptorType::Sampler and @ref DescriptorType::CombinedImageSampler +it's possible to specify a list of immutable @ref Sampler "Samplers" in place +of the descriptor count argument. The descriptor count is then implicitly taken +from size of the array. The above snippet with immutable samplers would look +like this: + +@snippet MagnumVk.cpp DescriptorSetLayout-creation-immutable-samplers + +@subsection Vk-DescriptorSetLayout-creation-binding-flags Descriptor binding flags + +With Vulkan 1.2 or @vk_extension{EXT,descriptor_indexing} it's possible to +specify additional flags per binding. All of them require a certain +@ref DeviceFeature to be supported and enabled, see particular +@ref DescriptorSetLayoutBinding::Flag for more information: + +@snippet MagnumVk.cpp DescriptorSetLayout-creation-binding-flags +*/ +class MAGNUM_VK_EXPORT DescriptorSetLayout { + public: + /** + * @brief Wrap existing Vulkan handle + * @param device Vulkan device the descriptor set layout is + * created on + * @param handle The @type_vk{DescriptorSetLayout} handle + * @param flags Handle flags + * + * The @p handle is expected to be originating from @p device. Unlike + * a descriptor set layout created using a constructor, the Vulkan + * descriptor set layout is by default not deleted on destruction, use + * @p flags for different behavior. + * @see @ref release() + */ + static DescriptorSetLayout wrap(Device& device, VkDescriptorSetLayout handle, HandleFlags flags = {}); + + /** + * @brief Constructor + * @param device Vulkan device to create the descriptor set layout + * on + * @param info Descriptor set layout creation info + * + * @see @fn_vk_keyword{CreateDescriptorSetLayout} + */ + explicit DescriptorSetLayout(Device& device, const DescriptorSetLayoutCreateInfo& info); + + /** + * @brief Construct without creating the descriptor set layout + * + * The constructed instance is equivalent to moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + */ + explicit DescriptorSetLayout(NoCreateT); + + /** @brief Copying is not allowed */ + DescriptorSetLayout(const DescriptorSetLayout&) = delete; + + /** @brief Move constructor */ + DescriptorSetLayout(DescriptorSetLayout&& other) noexcept; + + /** + * @brief Destructor + * + * Destroys associated @type_vk{DescriptorSetLayout} handle, unless the + * instance was created using @ref wrap() without + * @ref HandleFlag::DestroyOnDestruction specified. + * @see @fn_vk_keyword{DestroyDescriptorSetLayout}, @ref release() + */ + ~DescriptorSetLayout(); + + /** @brief Copying is not allowed */ + DescriptorSetLayout& operator=(const DescriptorSetLayout&) = delete; + + /** @brief Move assignment */ + DescriptorSetLayout& operator=(DescriptorSetLayout&& other) noexcept; + + /** @brief Underlying @type_vk{DescriptorSetLayout} handle */ + VkDescriptorSetLayout handle() { return _handle; } + /** @overload */ + operator VkDescriptorSetLayout() { return _handle; } + + /** @brief Handle flags */ + HandleFlags handleFlags() const { return _flags; } + + /** + * @brief Release the underlying Vulkan descriptor set layout + * + * Releases ownership of the Vulkan descriptor set layout and returns + * its handle so @fn_vk{DestroyDescriptorSetLayout} is not called on + * destruction. The internal state is then equivalent to moved-from + * state. + * @see @ref wrap() + */ + VkDescriptorSetLayout release(); + + private: + /* Can't be a reference because of the NoCreate constructor */ + Device* _device; + + VkDescriptorSetLayout _handle; + HandleFlags _flags; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h new file mode 100644 index 000000000..dcb62bfb2 --- /dev/null +++ b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h @@ -0,0 +1,480 @@ +#ifndef Magnum_Vk_DescriptorSetLayoutCreateInfo_h +#define Magnum_Vk_DescriptorSetLayoutCreateInfo_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Vk::DescriptorSetLayoutCreateInfo, @ref Magnum::Vk::DescriptorSetLayoutBinding, enum @ref Magnum::Vk::DescriptorType + * @m_since_latest + */ + +/* While I'm not commonly including the Reference headers, the constructor of + DescriptorSetLayoutCreateInfo needs this type and so users would be forced + to include it every time they include this header. Or forget to do so and + wonder why the code is not compiling, which especially when combined with + the fact that one has to wrap the DescriptorSetLayoutBinding instances in + double {{}}'s might be a bit too much to handle. */ +#include + +#include +#include + +#include "Magnum/Tags.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Descriptor type +@m_since_latest + +Wraps @type_vk_keyword{DescriptorType}. +@see @ref DescriptorSetLayoutBinding +@m_enum_values_as_keywords +*/ +enum class DescriptorType: Int { + /** + * @ref Sampler. + * + * @see @ref DescriptorType::CombinedImageSampler + */ + Sampler = VK_DESCRIPTOR_TYPE_SAMPLER, + + /** + * @ref Sampler combined with an @ref Image. + * + * @m_class{m-note m-success} + * + * @par + * On some implementations it may be more efficient to sample from an + * a combined image sampler than a separate + * @ref DescriptorType::Sampler and @ref DescriptorType::SampledImage. + * + * The image is expected to have been created with @ref ImageUsage::Sampled + * and be in either @ref ImageLayout::General or + * @ref ImageLayout::ShaderReadOnly. + */ + CombinedImageSampler = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + + /** + * Sampled @ref Image. + * + * The image is expected to have been created with @ref ImageUsage::Sampled + * and be in either @ref ImageLayout::General or + * @ref ImageLayout::ShaderReadOnly. + * @see @ref DescriptorType::CombinedImageSampler + */ + SampledImage = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + + /** + * Storage @ref Image. + * + * The image is expected to have been created with @ref ImageUsage::Storage + * and be in @ref ImageLayout::General. + */ + StorageImage = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + + /** + * Uniform texel buffer view. + * + * The buffer is expected to have been created with + * @ref BufferUsage::UniformTexelBuffer. + */ + UniformTexelBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + + /** + * Storage texel buffer view. + * + * The buffer is expected to have been created with + * @ref BufferUsage::StorageTexelBuffer. + */ + StorageTexelBuffer = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + + /** + * Uniform @ref Buffer. + * + * The buffer is expected to have been created with + * @ref BufferUsage::UniformBuffer. + */ + UniformBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + + /** + * Storage @ref Buffer. + * + * The buffer is expected to have been created with + * @ref BufferUsage::StorageBuffer. + */ + StorageBuffer = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + + /** + * Uniform @ref Buffer with a dynamic offset. + * + * The buffer is expected to have been created with + * @ref BufferUsage::UniformBuffer. + */ + UniformBufferDynamic = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + + /** + * Storage @ref Buffer with a dynamic offset. + * + * The buffer is expected to have been created with + * @ref BufferUsage::StorageBuffer. + */ + StorageBufferDynamic = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + + /** + * Input @ref Image attachment. + * + * The image is expected to have been created with + * @ref ImageUsage::InputAttachment and be in @ref ImageLayout::General. + */ + InputAttachment = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + + /** + * Acceleration structure. + * + * @requires_vk_feature @ref DeviceFeature::AccelerationStructure + */ + AccelerationStructure = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR +}; + +/** +@brief Descriptor set layout binding +@m_since_latest + +Wraps a @type_vk_keyword{DescriptorSetLayoutBinding} together with +associated @type_vk_keyword{DescriptorBindingFlags}. See +@ref Vk-DescriptorSetLayout-creation "Descriptor set layout creation" +for usage information. +*/ +class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { + public: + /** + * @brief Descriptor set layout binding flag + * + * Wraps @type_vk_keyword{DescriptorBindingFlagBits}. + * @see @ref Flags, @ref DescriptorSetLayoutBinding() + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + * @m_enum_values_as_keywords + */ + enum class Flag: UnsignedInt { + /** + * If descriptors in this binding are updated between + * binding them in a command buffer and a @ref Queue::submit(), the + * submission will use the most recently set descriptors for + * the binding and the updates do not invalidate the command + * buffer. + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingSampledImageUpdateAfterBind + * if used on a @ref DescriptorType::CombinedImageSampler / + * @relativeref{DescriptorType,SampledImage} + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingStorageImageUpdateAfterBind + * if used on a @ref DescriptorType::StorageImage + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingUniformTexelBufferUpdateAfterBind + * if used on a @ref DescriptorType::UniformTexelBuffer + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingStorageTexelBufferUpdateAfterBind + * if used on a @ref DescriptorType::StorageTexelBuffer + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind + * if used on a @ref DescriptorType::UniformBuffer / + * @relativeref{DescriptorType,UniformBufferDynamic} + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingStorageBufferUpdateAfterBind + * if used on a @ref DescriptorType::StorageBuffer / + * @relativeref{DescriptorType,StorageBufferDynamic} + */ + UpdateAfterBind = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, + + /** + * Descriptors not used by the command buffer can be updated + * after binding them in a command buffer and while the command + * buffer is pending execution. If set together with + * @ref Flag::PartiallyBound, any descriptors that are not + * dynamically used can be updated, if alone then only descriptors + * statically not used can be updated. + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingUpdateUnusedWhilePending + */ + UpdateUnusedWhilePending = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT, + + /** + * Descriptors in the binding that are not dynamically used don't + * need to contain valid descriptors when consumed. + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingPartiallyBound + */ + PartiallyBound = VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT, + + /** + * This descriptor binding has a variable size that will be + * specified when a descriptor set is allocated using this layout, + * and the @p descriptorCount value is treated as an upper bound. + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingVariableDescriptorCount + */ + VariableDescriptorCount = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT + }; + + /** + * @brief Descriptor set layout creation flags + * + * Type-safe wrapper for @type_vk_keyword{DescriptorBindingFlags}. + * @see @ref DescriptorSetLayoutBinding() + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} + */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param binding Binding corresponding to a particular + * binding in a shader + * @param descriptorType Descriptor type + * @param descriptorCount Number of descriptors contained in the + * binding. Has to be at least @cpp 1 @ce. If the shader binding + * is not an array, use @cpp 1 @ce. + * @param stages Shader stages that access the binding. + * Use @cpp ~Vk::ShaderStages{} @ce to specify that all stages + * may access the binding. + * @param flags Flags + * + * The following @type_vk{DescriptorSetLayoutBinding} fields are + * pre-filled, everything else is zero-filled: + * + * - `binding` + * - `descriptorType` + * - `descriptorCount` + * - `stageFlags` to @p stages + * + * If @p flags are non-empty, a @type_vk{DescriptorBindingFlags} field + * is saved and then subsequently available through @ref flags(). + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} if + * @p flags are non-empty + */ + /*implicit*/ DescriptorSetLayoutBinding(UnsignedInt binding, DescriptorType descriptorType, UnsignedInt descriptorCount = 1, ShaderStages stages = ~ShaderStages{}, Flags flags = {}); + + /** + * @brief Construct with immutable samplers + * @param binding Binding corresponding to a particular + * binding in a shader + * @param descriptorType Descriptor type. Should be either + * @ref DescriptorType::Sampler or + * @ref DescriptorType::CombinedImageSampler. + * @param immutableSamplers Immutable samplers + * @param stages Shader stages that access the binding. + * Use @cpp ~Vk::ShaderStages{} @ce to specify that all stages + * may access the binding. + * @param flags Flags + * + * The following @type_vk{DescriptorSetLayoutBinding} fields are + * pre-filled, everything else is zero-filled: + * + * - `binding` + * - `descriptorType` + * - `descriptorCount` to @cpp immutableSamplers.size() @ce + * - `pImmutableSamplers` to a copy of @p immutableSamplers + * - `stageFlags` to @p stages + * + * If @p flags are non-empty, a @type_vk{DescriptorBindingFlags} field + * is saved and then subsequently available through @ref flags(). + * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} if + * @p flags are non-empty + */ + /*implicit*/ DescriptorSetLayoutBinding(UnsignedInt binding, DescriptorType descriptorType, Containers::ArrayView immutableSamplers, ShaderStages stages = ~ShaderStages{}, Flags flags = {}); + /** @overload */ + /*implicit*/ DescriptorSetLayoutBinding(UnsignedInt binding, DescriptorType descriptorType, std::initializer_list immutableSamplers, ShaderStages stages = ~ShaderStages{}, Flags flags = {}); + + /** + * @brief Construct without initializing the contents + * + * Note that the structure has to be fully initialized afterwards in + * order to be usable. + */ + explicit DescriptorSetLayoutBinding(NoInitT) noexcept; + + /** + * @brief Construct from existing data + * + * Copies the existing values verbatim, pointers are kept unchanged + * without taking over the ownership. Modifying the newly created + * instance will not modify the original data nor the pointed-to data. + */ + explicit DescriptorSetLayoutBinding(const VkDescriptorSetLayoutBinding& info, VkDescriptorBindingFlags flags = {}); + + /** @brief Copying is not allowed */ + DescriptorSetLayoutBinding(const DescriptorSetLayoutBinding&) = delete; + + /** @brief Move constructor */ + DescriptorSetLayoutBinding(DescriptorSetLayoutBinding&& other) noexcept; + + ~DescriptorSetLayoutBinding(); + + /** @brief Copying is not allowed */ + DescriptorSetLayoutBinding& operator=(const DescriptorSetLayoutBinding&) = delete; + + /** @brief Move assignment */ + DescriptorSetLayoutBinding& operator=(DescriptorSetLayoutBinding&& other) noexcept; + + /** @brief Underlying @type_vk{DescriptorSetLayoutBinding} structure */ + VkDescriptorSetLayoutBinding& operator*() { return _binding; } + /** @overload */ + const VkDescriptorSetLayoutBinding& operator*() const { return _binding; } + /** @overload */ + VkDescriptorSetLayoutBinding* operator->() { return &_binding; } + /** @overload */ + const VkDescriptorSetLayoutBinding* operator->() const { return &_binding; } + /** @overload */ + operator const VkDescriptorSetLayoutBinding*() const { return &_binding; } + + /** + * @overload + * + * The class is implicitly convertible to a reference in addition to + * a pointer because the type is commonly used in arrays as well, which + * would be annoying to do with a pointer conversion. + */ + operator const VkDescriptorSetLayoutBinding&() const { return _binding; } + + /** @brief Underlying @type_vk{DescriptorBindingFlags} enum set */ + VkDescriptorBindingFlags& flags() { return _flags; } + /** @overload */ + VkDescriptorBindingFlags flags() const { return _flags; } + + private: + VkDescriptorSetLayoutBinding _binding; + Containers::ArrayTuple _data; + VkDescriptorBindingFlags _flags; +}; + +CORRADE_ENUMSET_OPERATORS(DescriptorSetLayoutBinding::Flags) + +/** +@brief Descriptor set layout creation info +@m_since_latest + +Wraps a @type_vk_keyword{DescriptorSetLayoutCreateInfo} together with +@type_vk_keyword{DescriptorSetLayoutBindingFlagsCreateInfo}. See +@ref Vk-DescriptorSetLayout-creation "Descriptor set layout creation" +for usage information. +*/ +class MAGNUM_VK_EXPORT DescriptorSetLayoutCreateInfo { + public: + /** + * @brief Descriptor set layout creation flag + * + * Wraps @type_vk_keyword{DescriptorSetLayoutCreateFlagBits}. + * @see @ref Flags, @ref DescriptorSetLayoutCreateInfo() + * @m_enum_values_as_keywords + */ + enum class Flag: UnsignedInt { + /** @todo all the flags from extensions and 1.2 */ + }; + + /** + * @brief Descriptor set layout creation flags + * + * Type-safe wrapper for @type_vk_keyword{DescriptorSetLayoutCreateFlags}. + * @see @ref DescriptorSetLayoutCreateInfo() + */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param bindings Descriptor set layout bindings. At least one + * binding has to be present. + * @param flags Descriptor set layout creation flags + * + * The following @type_vk{DescriptorSetLayoutCreateInfo} fields are + * pre-filled in addition to `sType`, everything else is zero-filled: + * + * - `flags` + * - `bindingCount` to @cpp bindings.size() @ce + * - `pBindings` to a copy of @p bindings + * + * If any of the @p bindings has @ref DescriptorSetLayoutBinding::flags() + * non-empty, a @type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} + * structure is referenced from the `pNext` chain of + * @type_vk{DescriptorSetLayoutCreateInfo}, with the following fields + * set in addition to `sType`, everything else zero-filled: + * + * - `bindingCount` to @cpp binding.size() @ce + * - `pBindingFlags` to a list of all + * @ref DescriptorSetLayoutBinding::flags() from @p bindings + */ + explicit DescriptorSetLayoutCreateInfo(Containers::ArrayView> bindings, Flags flags = {}); + /** @overload */ + explicit DescriptorSetLayoutCreateInfo(std::initializer_list> bindings, Flags flags = {}); + + /** + * @brief Construct without initializing the contents + * + * Note that not even the `sType` field is set --- the structure has to + * be fully initialized afterwards in order to be usable. + */ + explicit DescriptorSetLayoutCreateInfo(NoInitT) noexcept; + + /** + * @brief Construct from existing data + * + * Copies the existing values verbatim, pointers are kept unchanged + * without taking over the ownership. Modifying the newly created + * instance will not modify the original data nor the pointed-to data. + */ + explicit DescriptorSetLayoutCreateInfo(const VkDescriptorSetLayoutCreateInfo& info); + + /** @brief Copying is not allowed */ + DescriptorSetLayoutCreateInfo(const DescriptorSetLayoutCreateInfo&) = delete; + + /** @brief Move constructor */ + DescriptorSetLayoutCreateInfo(DescriptorSetLayoutCreateInfo&& other) noexcept; + + ~DescriptorSetLayoutCreateInfo(); + + /** @brief Copying is not allowed */ + DescriptorSetLayoutCreateInfo& operator=(const DescriptorSetLayoutCreateInfo&) = delete; + + /** @brief Move assignment */ + DescriptorSetLayoutCreateInfo& operator=(DescriptorSetLayoutCreateInfo&& other) noexcept; + + /** @brief Underlying @type_vk{DescriptorSetLayoutCreateInfo} structure */ + VkDescriptorSetLayoutCreateInfo& operator*() { return _info; } + /** @overload */ + const VkDescriptorSetLayoutCreateInfo& operator*() const { return _info; } + /** @overload */ + VkDescriptorSetLayoutCreateInfo* operator->() { return &_info; } + /** @overload */ + const VkDescriptorSetLayoutCreateInfo* operator->() const { return &_info; } + /** @overload */ + operator const VkDescriptorSetLayoutCreateInfo*() const { return &_info; } + + private: + VkDescriptorSetLayoutCreateInfo _info; + Containers::ArrayTuple _data; +}; + +CORRADE_ENUMSET_OPERATORS(DescriptorSetLayoutCreateInfo::Flags) + +}} + +/* Make the definition complete -- it doesn't make sense to have a CreateInfo + without the corresponding object anyway. */ +#include "Magnum/Vk/DescriptorSetLayout.h" + +#endif diff --git a/src/Magnum/Vk/DeviceFeatures.h b/src/Magnum/Vk/DeviceFeatures.h index 1d5d4c34c..00a68f61e 100644 --- a/src/Magnum/Vk/DeviceFeatures.h +++ b/src/Magnum/Vk/DeviceFeatures.h @@ -876,81 +876,95 @@ enum class DeviceFeature: UnsignedShort { ShaderStorageTexelBufferArrayNonUniformIndexing, /** - * Whether uniform buffer descriptors can be updated after a set is bound. + * Whether @ref DescriptorType::UniformBuffer / + * @relativeref{DescriptorType,UniformBufferDynamic} can be updated after a + * set is bound. * @see @ref DeviceFeature::DescriptorBindingAccelerationStructureUpdateAfterBind, * @relativeref{DeviceFeature,DescriptorBindingSampledImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageBufferUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingUniformTexelBufferUpdateAfterBind}, - * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind} + * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind}, + * @ref DescriptorSetLayoutBinding::Flag::UpdateAfterBind * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingUniformBufferUpdateAfterBind, /** - * Whether sampled image descriptors can be updated after a set is bound. + * Whether @ref DescriptorType::CombinedImageSampler / + * @relativeref{DescriptorType,SampledImage} can be updated after a set is + * bound. * @see @ref DeviceFeature::DescriptorBindingAccelerationStructureUpdateAfterBind, * @relativeref{DeviceFeature,DescriptorBindingUniformBufferUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageBufferUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingUniformTexelBufferUpdateAfterBind}, - * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind} + * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind}, + * @ref DescriptorSetLayoutBinding::Flag::UpdateAfterBind * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingSampledImageUpdateAfterBind, /** - * Whether storage image descriptors can be updated after a set is bound. + * Whether @ref DescriptorType::StorageImage can be updated after a set is + * bound. * @see @ref DeviceFeature::DescriptorBindingAccelerationStructureUpdateAfterBind, * @relativeref{DeviceFeature,DescriptorBindingUniformBufferUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingSampledImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageBufferUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingUniformTexelBufferUpdateAfterBind}, - * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind} + * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind}, + * @ref DescriptorSetLayoutBinding::Flag::UpdateAfterBind * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingStorageImageUpdateAfterBind, /** - * Whether storage buffer descriptors can be updated after a set is bound. + * Whether @ref DescriptorType::StorageBuffer / + * @relativeref{DescriptorType,StorageBufferDynamic} can be updated after a + * set is bound. * @see @ref DeviceFeature::DescriptorBindingAccelerationStructureUpdateAfterBind, * @relativeref{DeviceFeature,DescriptorBindingUniformBufferUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingSampledImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingUniformTexelBufferUpdateAfterBind}, - * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind} + * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind}, + * @ref DescriptorSetLayoutBinding::Flag::UpdateAfterBind * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingStorageBufferUpdateAfterBind, /** - * Whether uniform texel buffer descriptors can be updated after a set is - * bound. + * Whether @ref DescriptorType::UniformTexelBuffer can be updated after a + * set is bound. * @see @ref DeviceFeature::DescriptorBindingAccelerationStructureUpdateAfterBind, * @relativeref{DeviceFeature,DescriptorBindingUniformBufferUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingSampledImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageBufferUpdateAfterBind}, - * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind} + * @relativeref{DeviceFeature,DescriptorBindingStorageTexelBufferUpdateAfterBind}, + * @ref DescriptorSetLayoutBinding::Flag::UpdateAfterBind * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingUniformTexelBufferUpdateAfterBind, /** - * Whether storage texel buffer descriptors can be updated after a set is - * bound. + * Whether @ref DescriptorType::StorageTexelBuffer can be updated after a + * set is bound. * @see @ref DeviceFeature::DescriptorBindingAccelerationStructureUpdateAfterBind, * @relativeref{DeviceFeature,DescriptorBindingUniformBufferUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingSampledImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageImageUpdateAfterBind}, * @relativeref{DeviceFeature,DescriptorBindingStorageBufferUpdateAfterBind}, - * @relativeref{DeviceFeature,DescriptorBindingUniformTexelBufferUpdateAfterBind} + * @relativeref{DeviceFeature,DescriptorBindingUniformTexelBufferUpdateAfterBind}, + * @ref DescriptorSetLayoutBinding::Flag::UpdateAfterBind * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingStorageTexelBufferUpdateAfterBind, /** * Whether descriptors can be updated while the set is in use. + * @see @ref DescriptorSetLayoutBinding::Flag::UpdateUnusedWhilePending * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingUpdateUnusedWhilePending, @@ -958,6 +972,7 @@ enum class DeviceFeature: UnsignedShort { /** * Whether a descriptor set binding in which some descriptors are not valid * can be statically used. + * @see @ref DescriptorSetLayoutBinding::Flag::PartiallyBound * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingPartiallyBound, @@ -965,6 +980,7 @@ enum class DeviceFeature: UnsignedShort { /** * Whether descriptor sets with a variably-sized last binding are * supported. + * @see @ref DescriptorSetLayoutBinding::Flag::VariableDescriptorCount * @requires_vk12 Extension @vk_extension{EXT,descriptor_indexing} */ DescriptorBindingVariableDescriptorCount, diff --git a/src/Magnum/Vk/Image.h b/src/Magnum/Vk/Image.h index 138646647..3b831485c 100644 --- a/src/Magnum/Vk/Image.h +++ b/src/Magnum/Vk/Image.h @@ -133,6 +133,9 @@ enum class ImageLayout: Int { * * Only valid for images created with @ref ImageUsage::Sampled or * @ref ImageUsage::InputAttachment. + * @see @ref DescriptorType::CombinedImageSampler, + * @ref DescriptorType::SampledImage, + * @ref DescriptorType::InputAttachment */ ShaderReadOnly = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, diff --git a/src/Magnum/Vk/ImageCreateInfo.h b/src/Magnum/Vk/ImageCreateInfo.h index 0e0a656a2..02ed20291 100644 --- a/src/Magnum/Vk/ImageCreateInfo.h +++ b/src/Magnum/Vk/ImageCreateInfo.h @@ -82,7 +82,8 @@ enum class ImageUsage: UnsignedInt { * * Not all pixel formats support sampling, see @ref PixelFormat for more * information. - * @see @ref ImageLayout::ShaderReadOnly + * @see @ref ImageLayout::ShaderReadOnly, + * @ref DescriptorType::SampledImage */ Sampled = VK_IMAGE_USAGE_SAMPLED_BIT, @@ -92,7 +93,8 @@ enum class ImageUsage: UnsignedInt { * Not all pixel formats support shader storage, with some requiring the * @ref DeviceFeature::ShaderStorageImageExtendedFormats feature. See * @ref PixelFormat for more information. - * @see @ref ImageLayout::General + * @see @ref ImageLayout::General, + * @ref DescriptorType::StorageImage */ Storage = VK_IMAGE_USAGE_STORAGE_BIT, @@ -125,6 +127,7 @@ enum class ImageUsage: UnsignedInt { * Input attachment in a shader or framebuffer * * @see @ref ImageLayout::ShaderReadOnly, + * @ref DescriptorType::InputAttachment, * @ref SubpassDescription::setInputAttachments() */ InputAttachment = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index 7738e9936..04ca80668 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -27,6 +27,7 @@ corrade_add_test(VkBufferTest BufferTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkCommandBufferTest CommandBufferTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk) +corrade_add_test(VkDescriptorSetLayoutTest DescriptorSetLayoutTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceTest DeviceTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDevicePropertiesTest DevicePropertiesTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceFeaturesTest DeviceFeaturesTest.cpp LIBRARIES MagnumVk) @@ -129,6 +130,7 @@ set_target_properties( VkBufferTest VkCommandBufferTest VkCommandPoolTest + VkDescriptorSetLayoutTest VkDeviceTest VkDeviceFeaturesTest VkDevicePropertiesTest @@ -192,6 +194,7 @@ if(BUILD_VK_TESTS) corrade_add_test(VkBufferVkTest BufferVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkCommandBufferVkTest CommandBufferVkTest.cpp LIBRARIES MagnumVulkanTester) corrade_add_test(VkCommandPoolVkTest CommandPoolVkTest.cpp LIBRARIES MagnumVulkanTester) + corrade_add_test(VkDescriptorSetLayoutVkTest DescriptorSetLayoutVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkDeviceVkTest DeviceVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkDevicePropertiesVkTest DevicePropertiesVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkExtensionPropertiesVkTest ExtensionPropertiesVkTest.cpp LIBRARIES MagnumVkTestLib) @@ -243,6 +246,7 @@ if(BUILD_VK_TESTS) VkBufferVkTest VkCommandBufferVkTest VkCommandPoolVkTest + VkDescriptorSetLayoutVkTest VkDeviceVkTest VkDevicePropertiesVkTest VkExtensionPropertiesVkTest diff --git a/src/Magnum/Vk/Test/DescriptorSetLayoutTest.cpp b/src/Magnum/Vk/Test/DescriptorSetLayoutTest.cpp new file mode 100644 index 000000000..750d41128 --- /dev/null +++ b/src/Magnum/Vk/Test/DescriptorSetLayoutTest.cpp @@ -0,0 +1,320 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 +#include + +#include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" +#include "Magnum/Vk/Shader.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DescriptorSetLayoutTest: TestSuite::Tester { + explicit DescriptorSetLayoutTest(); + + void bindingConstruct(); + void bindingConstructCountStages(); + void bindingConstructFlags(); + void bindingConstructImmutableSamplers(); + void bindingConstructNoInit(); + void bindingConstructFromVk(); + void bindingConstructCopy(); + void bindingConstructMove(); + + void createInfoConstruct(); + void createInfoConstructBindingFlags(); + void createInfoConstructBindingImmutableSamplers(); + void createInfoConstructNoInit(); + void createInfoConstructFromVk(); + void createInfoConstructCopy(); + void createInfoConstructMove(); + + void constructNoCreate(); + void constructCopy(); +}; + +DescriptorSetLayoutTest::DescriptorSetLayoutTest() { + addTests({&DescriptorSetLayoutTest::bindingConstruct, + &DescriptorSetLayoutTest::bindingConstructCountStages, + &DescriptorSetLayoutTest::bindingConstructFlags, + &DescriptorSetLayoutTest::bindingConstructImmutableSamplers, + &DescriptorSetLayoutTest::bindingConstructNoInit, + &DescriptorSetLayoutTest::bindingConstructFromVk, + &DescriptorSetLayoutTest::bindingConstructCopy, + &DescriptorSetLayoutTest::bindingConstructMove, + + &DescriptorSetLayoutTest::createInfoConstruct, + &DescriptorSetLayoutTest::createInfoConstructBindingFlags, + &DescriptorSetLayoutTest::createInfoConstructBindingImmutableSamplers, + &DescriptorSetLayoutTest::createInfoConstructNoInit, + &DescriptorSetLayoutTest::createInfoConstructFromVk, + &DescriptorSetLayoutTest::createInfoConstructCopy, + &DescriptorSetLayoutTest::createInfoConstructMove, + + &DescriptorSetLayoutTest::constructNoCreate, + &DescriptorSetLayoutTest::constructCopy}); +} + +void DescriptorSetLayoutTest::bindingConstruct() { + DescriptorSetLayoutBinding binding{15, DescriptorType::SampledImage}; + CORRADE_COMPARE(binding->binding, 15); + CORRADE_COMPARE(binding->descriptorType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + CORRADE_COMPARE(binding->descriptorCount, 1); + CORRADE_VERIFY(!binding->pImmutableSamplers); + CORRADE_COMPARE(binding->stageFlags, VK_SHADER_STAGE_ALL); + CORRADE_COMPARE(binding.flags(), 0); +} + +void DescriptorSetLayoutTest::bindingConstructCountStages() { + DescriptorSetLayoutBinding binding{15, DescriptorType::SampledImage, 5, ShaderStage::Fragment|ShaderStage::RayMiss}; + CORRADE_COMPARE(binding->binding, 15); + CORRADE_COMPARE(binding->descriptorType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + CORRADE_COMPARE(binding->descriptorCount, 5); + CORRADE_VERIFY(!binding->pImmutableSamplers); + CORRADE_COMPARE(binding->stageFlags, VK_SHADER_STAGE_FRAGMENT_BIT|VK_SHADER_STAGE_MISS_BIT_KHR); + CORRADE_COMPARE(binding.flags(), 0); +} + +void DescriptorSetLayoutTest::bindingConstructFlags() { + DescriptorSetLayoutBinding binding{15, DescriptorType::SampledImage, 2, ShaderStage::Fragment, DescriptorSetLayoutBinding::Flag::UpdateAfterBind|DescriptorSetLayoutBinding::Flag::PartiallyBound}; + CORRADE_COMPARE(binding->binding, 15); + CORRADE_COMPARE(binding->descriptorType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + CORRADE_COMPARE(binding->descriptorCount, 2); + CORRADE_VERIFY(!binding->pImmutableSamplers); + CORRADE_COMPARE(binding->stageFlags, VK_SHADER_STAGE_FRAGMENT_BIT); + CORRADE_COMPARE(binding.flags(), VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT|VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT); +} + +void DescriptorSetLayoutTest::bindingConstructImmutableSamplers() { + DescriptorSetLayoutBinding binding{15, DescriptorType::SampledImage, {reinterpret_cast(0xdead), reinterpret_cast(0xbeef), reinterpret_cast(0xcafe)}, ShaderStage::Fragment, DescriptorSetLayoutBinding::Flag::UpdateAfterBind}; + CORRADE_COMPARE(binding->binding, 15); + CORRADE_COMPARE(binding->descriptorType, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); + CORRADE_COMPARE(binding->descriptorCount, 3); + CORRADE_VERIFY(binding->pImmutableSamplers); + CORRADE_COMPARE(binding->pImmutableSamplers[0], reinterpret_cast(0xdead)); + CORRADE_COMPARE(binding->pImmutableSamplers[1], reinterpret_cast(0xbeef)); + CORRADE_COMPARE(binding->pImmutableSamplers[2], reinterpret_cast(0xcafe)); + CORRADE_COMPARE(binding->stageFlags, VK_SHADER_STAGE_FRAGMENT_BIT); + CORRADE_COMPARE(binding.flags(), VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT); +} + +void DescriptorSetLayoutTest::bindingConstructNoInit() { + VkSampler a; + DescriptorSetLayoutBinding info{NoInit}; + info->pImmutableSamplers = &a; + new(&info) DescriptorSetLayoutBinding{NoInit}; + CORRADE_COMPARE(info->pImmutableSamplers, &a); + + CORRADE_VERIFY(std::is_nothrow_constructible::value); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +void DescriptorSetLayoutTest::bindingConstructFromVk() { + VkSampler a; + + VkDescriptorSetLayoutBinding vkInfo; + vkInfo.pImmutableSamplers = &a; + + DescriptorSetLayoutBinding info{vkInfo}; + CORRADE_COMPARE(info->pImmutableSamplers, &a); +} + +void DescriptorSetLayoutTest::bindingConstructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +void DescriptorSetLayoutTest::bindingConstructMove() { + DescriptorSetLayoutBinding a{15, DescriptorType::SampledImage, {reinterpret_cast(0xdead), reinterpret_cast(0xbeef), reinterpret_cast(0xcafe)}, ShaderStage::Fragment, DescriptorSetLayoutBinding::Flag::UpdateAfterBind}; + CORRADE_COMPARE(a->descriptorCount, 3); + CORRADE_VERIFY(a->pImmutableSamplers); + CORRADE_COMPARE(a->pImmutableSamplers[1], reinterpret_cast(0xbeef)); + + DescriptorSetLayoutBinding b = std::move(a); + CORRADE_VERIFY(!a->pImmutableSamplers); + CORRADE_COMPARE(b->descriptorCount, 3); + CORRADE_VERIFY(b->pImmutableSamplers); + CORRADE_COMPARE(b->pImmutableSamplers[1], reinterpret_cast(0xbeef)); + CORRADE_COMPARE(b.flags(), VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT); + + DescriptorSetLayoutBinding c{3, {}}; + c = std::move(b); + CORRADE_VERIFY(!b->pImmutableSamplers); + CORRADE_COMPARE(c->descriptorCount, 3); + CORRADE_VERIFY(c->pImmutableSamplers); + CORRADE_COMPARE(c->pImmutableSamplers[1], reinterpret_cast(0xbeef)); + CORRADE_COMPARE(c.flags(), VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT); +} + +void DescriptorSetLayoutTest::createInfoConstruct() { + DescriptorSetLayoutCreateInfo info{{ + /* I hope the {{ will no longer be needed with C++14? */ + {{7, DescriptorType::UniformBuffer}}, + {{12, DescriptorType::CombinedImageSampler}} + }, DescriptorSetLayoutCreateInfo::Flag(VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT)}; + CORRADE_COMPARE(info->bindingCount, 2); + CORRADE_VERIFY(info->pBindings); + CORRADE_COMPARE(info->pBindings[0].binding, 7); + CORRADE_COMPARE(info->pBindings[0].descriptorType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + CORRADE_COMPARE(info->pBindings[0].descriptorCount, 1); + CORRADE_COMPARE(info->pBindings[1].binding, 12); + CORRADE_COMPARE(info->pBindings[1].descriptorType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + CORRADE_COMPARE(info->pBindings[1].descriptorCount, 1); + CORRADE_COMPARE(info->flags, VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT); + CORRADE_VERIFY(!info->pNext); +} + +void DescriptorSetLayoutTest::createInfoConstructBindingFlags() { + DescriptorSetLayoutCreateInfo info{{ + {{7, DescriptorType::UniformBuffer}}, + {{12, DescriptorType::CombinedImageSampler, 1, ~ShaderStages{}, DescriptorSetLayoutBinding::Flag::PartiallyBound}} + }}; + CORRADE_COMPARE(info->bindingCount, 2); + CORRADE_VERIFY(info->pBindings); + CORRADE_COMPARE(info->pBindings[0].binding, 7); + CORRADE_COMPARE(info->pBindings[0].descriptorType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + CORRADE_COMPARE(info->pBindings[0].descriptorCount, 1); + CORRADE_COMPARE(info->pBindings[1].binding, 12); + CORRADE_COMPARE(info->pBindings[1].descriptorType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + CORRADE_COMPARE(info->pBindings[1].descriptorCount, 1); + + CORRADE_VERIFY(info->pNext); + const auto& flags = *static_cast(info->pNext); + CORRADE_COMPARE(flags.bindingCount, 2); + CORRADE_VERIFY(flags.pBindingFlags); + CORRADE_COMPARE(flags.pBindingFlags[0], 0); + CORRADE_COMPARE(flags.pBindingFlags[1], VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT); +} + +void DescriptorSetLayoutTest::createInfoConstructBindingImmutableSamplers() { + DescriptorSetLayoutBinding binding{3, DescriptorType::Sampler, {reinterpret_cast(0xdead), reinterpret_cast(0xbeef)}}; + + DescriptorSetLayoutCreateInfo info{{ + {{7, DescriptorType::UniformBuffer}}, + binding, + {{12, DescriptorType::CombinedImageSampler, {reinterpret_cast(0xcafe)}}}, + }}; + CORRADE_COMPARE(info->bindingCount, 3); + CORRADE_VERIFY(info->pBindings); + + CORRADE_COMPARE(info->pBindings[0].binding, 7); + CORRADE_COMPARE(info->pBindings[0].descriptorType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + CORRADE_COMPARE(info->pBindings[0].descriptorCount, 1); + CORRADE_VERIFY(!info->pBindings[0].pImmutableSamplers); + + CORRADE_COMPARE(info->pBindings[1].binding, 3); + CORRADE_COMPARE(info->pBindings[1].descriptorType, VK_DESCRIPTOR_TYPE_SAMPLER); + CORRADE_COMPARE(info->pBindings[1].descriptorCount, 2); + CORRADE_VERIFY(info->pBindings[1].pImmutableSamplers); + /* The samplers should get copied, not referenced */ + CORRADE_VERIFY(info->pBindings[1].pImmutableSamplers != binding->pImmutableSamplers); + CORRADE_COMPARE(info->pBindings[1].pImmutableSamplers[0], reinterpret_cast(0xdead)); + CORRADE_COMPARE(info->pBindings[1].pImmutableSamplers[1], reinterpret_cast(0xbeef)); + + CORRADE_COMPARE(info->pBindings[2].binding, 12); + CORRADE_COMPARE(info->pBindings[2].descriptorType, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + CORRADE_COMPARE(info->pBindings[2].descriptorCount, 1); + CORRADE_VERIFY(info->pBindings[2].pImmutableSamplers); + CORRADE_COMPARE(info->pBindings[2].pImmutableSamplers[0], reinterpret_cast(0xcafe)); + + CORRADE_VERIFY(!info->pNext); +} + +void DescriptorSetLayoutTest::createInfoConstructNoInit() { + DescriptorSetLayoutCreateInfo info{NoInit}; + info->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + new(&info) DescriptorSetLayoutCreateInfo{NoInit}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); + + CORRADE_VERIFY(std::is_nothrow_constructible::value); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +void DescriptorSetLayoutTest::createInfoConstructFromVk() { + VkDescriptorSetLayoutCreateInfo vkInfo; + vkInfo.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + + DescriptorSetLayoutCreateInfo info{vkInfo}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); +} + +void DescriptorSetLayoutTest::createInfoConstructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +void DescriptorSetLayoutTest::createInfoConstructMove() { + DescriptorSetLayoutCreateInfo a{{ + {{7, DescriptorType::UniformBuffer}}, + {{12, DescriptorType::CombinedImageSampler, 1, ~ShaderStages{}, DescriptorSetLayoutBinding::Flag::PartiallyBound}} + }}; + CORRADE_COMPARE(a->bindingCount, 2); + CORRADE_VERIFY(a->pBindings); + CORRADE_VERIFY(a->pNext); + + DescriptorSetLayoutCreateInfo b = std::move(a); + CORRADE_COMPARE(a->bindingCount, 0); + CORRADE_VERIFY(!a->pBindings); + CORRADE_VERIFY(!a->pNext); + CORRADE_VERIFY(b->pBindings); + CORRADE_VERIFY(b->pNext); + CORRADE_COMPARE(b->pBindings[1].binding, 12); + CORRADE_VERIFY(static_cast(b->pNext)->pBindingFlags); + CORRADE_COMPARE(static_cast(b->pNext)->pBindingFlags[1], VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT); + + DescriptorSetLayoutCreateInfo c{VkDescriptorSetLayoutCreateInfo{}}; + c = std::move(b); + CORRADE_COMPARE(b->bindingCount, 0); + CORRADE_VERIFY(!b->pBindings); + CORRADE_VERIFY(!b->pNext); + CORRADE_VERIFY(c->pBindings); + CORRADE_VERIFY(c->pNext); + CORRADE_COMPARE(c->pBindings[1].binding, 12); + CORRADE_VERIFY(static_cast(c->pNext)->pBindingFlags); + CORRADE_COMPARE(static_cast(c->pNext)->pBindingFlags[1], VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT); +} + +void DescriptorSetLayoutTest::constructNoCreate() { + { + DescriptorSetLayout fence{NoCreate}; + CORRADE_VERIFY(!fence.handle()); + } + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +void DescriptorSetLayoutTest::constructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DescriptorSetLayoutTest) diff --git a/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp b/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp new file mode 100644 index 000000000..ca463eccc --- /dev/null +++ b/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp @@ -0,0 +1,104 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 + +#include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" +#include "Magnum/Vk/Result.h" +#include "Magnum/Vk/VulkanTester.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DescriptorSetLayoutVkTest: VulkanTester { + explicit DescriptorSetLayoutVkTest(); + + void construct(); + void constructMove(); + + void wrap(); +}; + +DescriptorSetLayoutVkTest::DescriptorSetLayoutVkTest() { + addTests({&DescriptorSetLayoutVkTest::construct, + &DescriptorSetLayoutVkTest::constructMove, + + &DescriptorSetLayoutVkTest::wrap}); +} + +void DescriptorSetLayoutVkTest::construct() { + { + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{ + {{15, DescriptorType::UniformBuffer}} + }}; + CORRADE_VERIFY(layout.handle()); + CORRADE_COMPARE(layout.handleFlags(), HandleFlag::DestroyOnDestruction); + } + + /* Shouldn't crash or anything */ + CORRADE_VERIFY(true); +} + +void DescriptorSetLayoutVkTest::constructMove() { + DescriptorSetLayout a{device(), DescriptorSetLayoutCreateInfo{ + {{15, DescriptorType::UniformBuffer}} + }}; + VkDescriptorSetLayout handle = a.handle(); + + DescriptorSetLayout b = std::move(a); + CORRADE_VERIFY(!a.handle()); + CORRADE_COMPARE(b.handle(), handle); + CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction); + + DescriptorSetLayout c{NoCreate}; + c = std::move(b); + CORRADE_VERIFY(!b.handle()); + CORRADE_COMPARE(b.handleFlags(), HandleFlags{}); + CORRADE_COMPARE(c.handle(), handle); + CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction); + + CORRADE_VERIFY(std::is_nothrow_move_constructible::value); + CORRADE_VERIFY(std::is_nothrow_move_assignable::value); +} + +void DescriptorSetLayoutVkTest::wrap() { + VkDescriptorSetLayout layout{}; + CORRADE_COMPARE(Result(device()->CreateDescriptorSetLayout(device(), + DescriptorSetLayoutCreateInfo{ + {{15, DescriptorType::UniformBuffer}} + }, + nullptr, &layout)), Result::Success); + + auto wrapped = DescriptorSetLayout::wrap(device(), layout, HandleFlag::DestroyOnDestruction); + CORRADE_COMPARE(wrapped.handle(), layout); + + /* Release the handle again, destroy by hand */ + CORRADE_COMPARE(wrapped.release(), layout); + CORRADE_VERIFY(!wrapped.handle()); + device()->DestroyDescriptorSetLayout(device(), layout, nullptr); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DescriptorSetLayoutVkTest) diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 68495270d..33b453d64 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -57,6 +57,9 @@ class CopyImageToBufferInfo; /* Not forward-declaring CopyBufferToImageInfo1D etc right now, I see no need */ enum class DependencyFlag: UnsignedInt; typedef Containers::EnumSet DependencyFlags; +class DescriptorSetLayout; +class DescriptorSetLayoutCreateInfo; +enum class DescriptorType: Int; class Device; class DeviceCreateInfo; enum class DeviceFeature: UnsignedShort; From 048a9a6a0b5d59681c2c007156ea65b144494a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 11 Mar 2021 13:14:05 +0100 Subject: [PATCH 083/161] Vk: add a short human-readable description to each Vulkan object. --- src/Magnum/Vk/CommandBuffer.h | 4 +++- src/Magnum/Vk/Device.h | 3 ++- src/Magnum/Vk/Fence.h | 3 ++- src/Magnum/Vk/Instance.h | 4 +++- src/Magnum/Vk/Memory.h | 1 + src/Magnum/Vk/Pipeline.h | 6 +++++- src/Magnum/Vk/Queue.h | 10 ++++++---- src/Magnum/Vk/Sampler.h | 3 ++- src/Magnum/Vk/Shader.h | 3 ++- 9 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/Magnum/Vk/CommandBuffer.h b/src/Magnum/Vk/CommandBuffer.h index 0fb488259..517d6addf 100644 --- a/src/Magnum/Vk/CommandBuffer.h +++ b/src/Magnum/Vk/CommandBuffer.h @@ -175,7 +175,9 @@ CORRADE_ENUMSET_OPERATORS(CommandBufferResetFlags) @brief Command buffer @m_since_latest -Wraps a @type_vk_keyword{CommandBuffer}. +Wraps a @type_vk_keyword{CommandBuffer}. Command buffers are used to record +all work done on a Vulkan device such as pipeline setup, draws, compute +dispatch or data transfers. @section Vk-CommandBuffer-allocation Command buffer allocation and recycling diff --git a/src/Magnum/Vk/Device.h b/src/Magnum/Vk/Device.h index 4b5ef53d5..84b4f8c45 100644 --- a/src/Magnum/Vk/Device.h +++ b/src/Magnum/Vk/Device.h @@ -54,7 +54,8 @@ namespace Implementation { @m_since_latest Wraps a @type_vk_keyword{Device} and stores device-specific Vulkan function -pointers. +pointers. A device provides an abstraction over a physical GPU or a CPU with +Vulkan capabilities. @section Vk-Device-creation Device creation diff --git a/src/Magnum/Vk/Fence.h b/src/Magnum/Vk/Fence.h index e695fe770..09e9558a9 100644 --- a/src/Magnum/Vk/Fence.h +++ b/src/Magnum/Vk/Fence.h @@ -45,7 +45,8 @@ namespace Magnum { namespace Vk { @brief Fence @m_since_latest -Wraps a @type_vk_keyword{Fence}. +Wraps a @type_vk_keyword{Fence}, which is used for synchronizing the CPU to a +queue execution done on a Vulkan device. @section Vk-Fence-creation Fence creation diff --git a/src/Magnum/Vk/Instance.h b/src/Magnum/Vk/Instance.h index 7e1eec334..dbbf3b0b8 100644 --- a/src/Magnum/Vk/Instance.h +++ b/src/Magnum/Vk/Instance.h @@ -52,7 +52,9 @@ namespace Implementation { @m_since_latest Wraps a @type_vk_keyword{Instance} and stores instance-specific Vulkan function -pointers. +pointers. An instance provides device enumeration and management of Vulkan +layers that enable additional functionality such as command validation or +tracing / debugging. @section Vk-Instance-creation Instance creation diff --git a/src/Magnum/Vk/Memory.h b/src/Magnum/Vk/Memory.h index 2e4920dd7..c4042598d 100644 --- a/src/Magnum/Vk/Memory.h +++ b/src/Magnum/Vk/Memory.h @@ -119,6 +119,7 @@ MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, MemoryFlags value); @m_since_latest Wraps a @type_vk_keyword{DeviceMemory} and handles its allocation and mapping. +Device memory is backing Vulkan buffers, images and other objects. @section Vk-Memory-allocation Memory allocation diff --git a/src/Magnum/Vk/Pipeline.h b/src/Magnum/Vk/Pipeline.h index 694958db8..7595bafc5 100644 --- a/src/Magnum/Vk/Pipeline.h +++ b/src/Magnum/Vk/Pipeline.h @@ -76,7 +76,11 @@ MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, PipelineBindPoint value); @brief Pipeline @m_since_latest -Wraps a @type_vk_keyword{Pipeline}. +Wraps a @type_vk_keyword{Pipeline}. A pipeline contains all state for execution +of either rasterization commands or a compute dispatch and among other things +contains shaders, pipeline layout specifying how uniform buffers, samplers and +other resources are bound, or a render pass describing how framebuffer +attachments get used. @section Vk-Pipeline-creation-rasterization Rasterization pipeline creation diff --git a/src/Magnum/Vk/Queue.h b/src/Magnum/Vk/Queue.h index 97240bc6a..7664f1cfd 100644 --- a/src/Magnum/Vk/Queue.h +++ b/src/Magnum/Vk/Queue.h @@ -43,10 +43,12 @@ namespace Magnum { namespace Vk { @brief Queue @m_since_latest -Wraps a @type_vk_keyword{Queue}. See @ref Vk-Device-creation for information -about how queues are created and retrieved from a device and -@ref Vk-CommandBuffer-usage for an overview of recording and submitting -command buffers to a queue. +Wraps a @type_vk_keyword{Queue}, which is used to submit command buffers for +execution on the device. + +See @ref Vk-Device-creation for information about how queues are created and +retrieved from a device and @ref Vk-CommandBuffer-usage for an overview of +recording and submitting command buffers to a queue. @see @ref DeviceCreateInfo::addQueues(), @ref submit() */ class MAGNUM_VK_EXPORT Queue { diff --git a/src/Magnum/Vk/Sampler.h b/src/Magnum/Vk/Sampler.h index 26ca1d36c..b9ff8e237 100644 --- a/src/Magnum/Vk/Sampler.h +++ b/src/Magnum/Vk/Sampler.h @@ -42,7 +42,8 @@ namespace Magnum { namespace Vk { @brief Sampler @m_since_latest -Wraps a @type_vk_keyword{Sampler}. +Wraps a @type_vk_keyword{Sampler}, which describes how shaders perform +texturing. @section Vk-Sampler-creation Sampler creation diff --git a/src/Magnum/Vk/Shader.h b/src/Magnum/Vk/Shader.h index 5b0ee47fe..100ae29f3 100644 --- a/src/Magnum/Vk/Shader.h +++ b/src/Magnum/Vk/Shader.h @@ -129,7 +129,8 @@ CORRADE_ENUMSET_OPERATORS(ShaderStages) @brief Shader @m_since_latest -Wraps a @type_vk_keyword{ShaderModule}. +Wraps a @type_vk_keyword{ShaderModule}, which contains a SPIR-V binary with one +or more shader entrypoints. @section Vk-Shader-creation Shader creation From 8bb1da98b9c41fd0baa2246759721d8b8196a36b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 11 Mar 2021 21:26:58 +0100 Subject: [PATCH 084/161] Vk: MSVC and clones, WHAT ARE YOU DOING. --- src/Magnum/Vk/DescriptorSetLayout.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Vk/DescriptorSetLayout.cpp b/src/Magnum/Vk/DescriptorSetLayout.cpp index 6e0858432..c6a9becd8 100644 --- a/src/Magnum/Vk/DescriptorSetLayout.cpp +++ b/src/Magnum/Vk/DescriptorSetLayout.cpp @@ -123,7 +123,9 @@ DescriptorSetLayoutCreateInfo::DescriptorSetLayoutCreateInfo(const Containers::A bindingsCopy[i] = b; if(b->pImmutableSamplers) { Utility::copy( - {b->pImmutableSamplers, b->descriptorCount}, + /* Just {} makes MSVC (and clang-cl!!) pick ArrayView + for some reason */ + Containers::arrayView(b->pImmutableSamplers, b->descriptorCount), immutableSamplersCopy.slice(immutableSamplerOffset, immutableSamplerOffset + b->descriptorCount)); bindingsCopy[i].pImmutableSamplers = immutableSamplersCopy + immutableSamplerOffset; immutableSamplerOffset += b->descriptorCount; From c656c5529800d47695a2a4ea371443e6e59208c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 12 Mar 2021 16:57:41 +0100 Subject: [PATCH 085/161] Vk: ability to list descriptor set layouts in PipelineLayoutCreateInfo. --- doc/snippets/MagnumVk.cpp | 20 ++++++++- src/Magnum/Vk/DescriptorSetLayout.h | 6 +++ src/Magnum/Vk/PipelineLayout.cpp | 43 ++++++++++++++++++- src/Magnum/Vk/PipelineLayout.h | 18 +++++++- src/Magnum/Vk/PipelineLayoutCreateInfo.h | 36 +++++++++++++++- src/Magnum/Vk/Test/PipelineLayoutTest.cpp | 47 ++++++++++++++++++++- src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp | 30 +++++++++++-- 7 files changed, 191 insertions(+), 9 deletions(-) diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index 30bbdc89f..8d90b1047 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -55,7 +55,7 @@ #include "Magnum/Vk/MemoryAllocateInfo.h" #include "Magnum/Vk/Mesh.h" #include "Magnum/Vk/Pipeline.h" -#include "Magnum/Vk/PipelineLayout.h" +#include "Magnum/Vk/PipelineLayoutCreateInfo.h" #include "Magnum/Vk/PixelFormat.h" #include "Magnum/Vk/Queue.h" #include "Magnum/Vk/RasterizationPipelineCreateInfo.h" @@ -1021,6 +1021,24 @@ cmd.bindPipeline(pipeline); /* [Pipeline-usage] */ } +{ +Vk::Device device{NoCreate}; +/* The include should be a no-op here since it was already included above */ +/* [PipelineLayout-creation] */ +#include + +DOXYGEN_IGNORE() + +Vk::DescriptorSetLayout layout1{DOXYGEN_IGNORE(NoCreate)}; +Vk::DescriptorSetLayout layout2{DOXYGEN_IGNORE(NoCreate)}; +DOXYGEN_IGNORE() + +Vk::PipelineLayout{device, Vk::PipelineLayoutCreateInfo{ + layout1, layout2, DOXYGEN_IGNORE(layout1) +}}; +/* [PipelineLayout-creation] */ +} + { Vk::Device device{NoCreate}; /* The include should be a no-op here since it was already included above */ diff --git a/src/Magnum/Vk/DescriptorSetLayout.h b/src/Magnum/Vk/DescriptorSetLayout.h index 1e4c4167b..6d42d54a9 100644 --- a/src/Magnum/Vk/DescriptorSetLayout.h +++ b/src/Magnum/Vk/DescriptorSetLayout.h @@ -85,6 +85,12 @@ specify additional flags per binding. All of them require a certain @ref DescriptorSetLayoutBinding::Flag for more information: @snippet MagnumVk.cpp DescriptorSetLayout-creation-binding-flags + +@section Vk-DescriptorSetLayout-usage Descriptor set layout usage + +A descriptor set layout is used in a @ref PipelineLayout creation and +subsequently for descriptor set allocation from a descriptor pool. See the +corresponding class documentation for more information. */ class MAGNUM_VK_EXPORT DescriptorSetLayout { public: diff --git a/src/Magnum/Vk/PipelineLayout.cpp b/src/Magnum/Vk/PipelineLayout.cpp index 7c51015e1..a4e5bcd9c 100644 --- a/src/Magnum/Vk/PipelineLayout.cpp +++ b/src/Magnum/Vk/PipelineLayout.cpp @@ -26,16 +26,32 @@ #include "PipelineLayout.h" #include "PipelineLayoutCreateInfo.h" +#include +#include + #include "Magnum/Vk/Assert.h" #include "Magnum/Vk/Device.h" #include "Magnum/Vk/Result.h" namespace Magnum { namespace Vk { -PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(): _info{} { +PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const Containers::ArrayView descriptorSetLayouts): _info{} { + /* Make a copy of the descriptor set layout list */ + Containers::ArrayView descriptorSetLayoutsCopy; + _data = Containers::ArrayTuple{ + {Containers::NoInit, descriptorSetLayouts.size(), descriptorSetLayoutsCopy} + }; + Utility::copy(descriptorSetLayouts, descriptorSetLayoutsCopy); + _info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + _info.setLayoutCount = descriptorSetLayoutsCopy.size(); + _info.pSetLayouts = descriptorSetLayoutsCopy; } +PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(): PipelineLayoutCreateInfo{Containers::ArrayView{}} {} + +PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const std::initializer_list descriptorSetLayouts): PipelineLayoutCreateInfo{Containers::arrayView(descriptorSetLayouts)} {} + PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(NoInitT) noexcept {} PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const VkPipelineLayoutCreateInfo& info): @@ -43,6 +59,31 @@ PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const VkPipelineLayoutCreateI member instead of doing a copy */ _info(info) {} +PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(PipelineLayoutCreateInfo&& other) noexcept: + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _info(other._info), + _data{std::move(other._data)} +{ + /* Ensure the previous instance doesn't reference state that's now ours */ + /** @todo this is now more like a destructible move, do it more selectively + and clear only what's really ours and not external? */ + other._info.pNext = nullptr; + other._info.setLayoutCount = 0; + other._info.pSetLayouts = nullptr; + other._info.pushConstantRangeCount = 0; + other._info.pPushConstantRanges = nullptr; +} + +PipelineLayoutCreateInfo::~PipelineLayoutCreateInfo() = default; + +PipelineLayoutCreateInfo& PipelineLayoutCreateInfo::operator=(PipelineLayoutCreateInfo&& other) noexcept { + using std::swap; + swap(other._info, _info); + swap(other._data, _data); + return *this; +} + PipelineLayout PipelineLayout::wrap(Device& device, const VkPipelineLayout handle, const HandleFlags flags) { PipelineLayout out{NoCreate}; out._device = &device; diff --git a/src/Magnum/Vk/PipelineLayout.h b/src/Magnum/Vk/PipelineLayout.h index 2feec7f3d..828cc8a86 100644 --- a/src/Magnum/Vk/PipelineLayout.h +++ b/src/Magnum/Vk/PipelineLayout.h @@ -43,7 +43,23 @@ namespace Magnum { namespace Vk { @brief Pipeline layout @m_since_latest -Wraps a @type_vk_keyword{PipelineLayout}. Used in a @ref Pipeline. +Wraps a @type_vk_keyword{PipelineLayout}. Specifies what descriptor set layouts +and push constants are used in a @ref Pipeline. + +@section Vk-PipelineLayout-creation Pipeline layout creation + +Except for the rare case when your shader doesn't have any bindings, in which +case a default-constructed @ref PipelineLayoutCreateInfo would be enough, +you'll want to list @ref DescriptorSetLayout instances for all descriptor sets +needed by shaders in the pipeline: + +@snippet MagnumVk.cpp PipelineLayout-creation + +@section Vk-PipelineLayout-usage Pipeline layout usage + +Once created, the pipeline layout instance is used for @ref Pipeline creation +and for descriptor set binding. See the corresponding class documentation for +more information. */ class MAGNUM_VK_EXPORT PipelineLayout { public: diff --git a/src/Magnum/Vk/PipelineLayoutCreateInfo.h b/src/Magnum/Vk/PipelineLayoutCreateInfo.h index f6067d0a3..d259d453e 100644 --- a/src/Magnum/Vk/PipelineLayoutCreateInfo.h +++ b/src/Magnum/Vk/PipelineLayoutCreateInfo.h @@ -30,6 +30,8 @@ * @m_since_latest */ +#include + #include "Magnum/Tags.h" #include "Magnum/Vk/Vk.h" #include "Magnum/Vk/Vulkan.h" @@ -41,19 +43,34 @@ namespace Magnum { namespace Vk { @brief Pipeline layout creation info @m_since_latest -Wraps a @type_vk_keyword{PipelineLayoutCreateInfo}. +Wraps a @type_vk_keyword{PipelineLayoutCreateInfo}. See +@ref Vk-PipelineLayout-creation "Pipeline layout creation" for usage +information. */ class MAGNUM_VK_EXPORT PipelineLayoutCreateInfo { public: + /* VkPipelineLayoutCreateFlagBits is currently empty, so no reason + to expose */ + /** * @brief Constructor + * @param descriptorSetLayouts Descriptor set layouts used in this + * pipeline layout * * The following @type_vk{PipelineLayoutCreateInfo} fields are * pre-filled in addition to `sType`, everything else is zero-filled: * - * - (none) + * - `setLayoutCount` and `pSetLayouts` to a copy of + * @p descriptorSetLayouts */ + #ifdef DOXYGEN_GENERATING_OUTPUT + explicit PipelineLayoutCreateInfo(Containers::ArrayView descriptorSetLayouts = {}); + #else /* so we don't need to include ArrayView */ + explicit PipelineLayoutCreateInfo(Containers::ArrayView descriptorSetLayouts); explicit PipelineLayoutCreateInfo(); + #endif + /** @overload */ + explicit PipelineLayoutCreateInfo(std::initializer_list descriptorSetLayouts); /** * @brief Construct without initializing the contents @@ -72,6 +89,20 @@ class MAGNUM_VK_EXPORT PipelineLayoutCreateInfo { */ explicit PipelineLayoutCreateInfo(const VkPipelineLayoutCreateInfo& info); + /** @brief Copying is not allowed */ + PipelineLayoutCreateInfo(const PipelineLayoutCreateInfo&) = delete; + + /** @brief Move constructor */ + PipelineLayoutCreateInfo(PipelineLayoutCreateInfo&& other) noexcept; + + ~PipelineLayoutCreateInfo(); + + /** @brief Copying is not allowed */ + PipelineLayoutCreateInfo& operator=(const PipelineLayoutCreateInfo&) = delete; + + /** @brief Move assignment */ + PipelineLayoutCreateInfo& operator=(PipelineLayoutCreateInfo&& other) noexcept; + /** @brief Underlying @type_vk{PipelineLayoutCreateInfo} structure */ VkPipelineLayoutCreateInfo& operator*() { return _info; } /** @overload */ @@ -85,6 +116,7 @@ class MAGNUM_VK_EXPORT PipelineLayoutCreateInfo { private: VkPipelineLayoutCreateInfo _info; + Containers::ArrayTuple _data; }; }} diff --git a/src/Magnum/Vk/Test/PipelineLayoutTest.cpp b/src/Magnum/Vk/Test/PipelineLayoutTest.cpp index 10f19d631..62344f245 100644 --- a/src/Magnum/Vk/Test/PipelineLayoutTest.cpp +++ b/src/Magnum/Vk/Test/PipelineLayoutTest.cpp @@ -24,6 +24,7 @@ */ #include +#include #include #include "Magnum/Vk/PipelineLayoutCreateInfo.h" @@ -34,8 +35,11 @@ struct PipelineLayoutTest: TestSuite::Tester { explicit PipelineLayoutTest(); void createInfoConstruct(); + void createInfoConstructDescriptorSetLayouts(); void createInfoConstructNoInit(); void createInfoConstructFromVk(); + void createInfoConstructCopy(); + void createInfoConstructMove(); void constructNoCreate(); void constructCopy(); @@ -43,8 +47,11 @@ struct PipelineLayoutTest: TestSuite::Tester { PipelineLayoutTest::PipelineLayoutTest() { addTests({&PipelineLayoutTest::createInfoConstruct, + &PipelineLayoutTest::createInfoConstructDescriptorSetLayouts, &PipelineLayoutTest::createInfoConstructNoInit, &PipelineLayoutTest::createInfoConstructFromVk, + &PipelineLayoutTest::createInfoConstructCopy, + &PipelineLayoutTest::createInfoConstructMove, &PipelineLayoutTest::constructNoCreate, &PipelineLayoutTest::constructCopy}); @@ -52,8 +59,20 @@ PipelineLayoutTest::PipelineLayoutTest() { void PipelineLayoutTest::createInfoConstruct() { PipelineLayoutCreateInfo info; - /** @todo expand once there's actually something */ CORRADE_COMPARE(info->flags, 0); + CORRADE_COMPARE(info->setLayoutCount, 0); +} + +void PipelineLayoutTest::createInfoConstructDescriptorSetLayouts() { + VkDescriptorSetLayout layouts[]{reinterpret_cast(0xdead), reinterpret_cast(0xbeef)}; + + PipelineLayoutCreateInfo info{layouts}; + CORRADE_COMPARE(info->setLayoutCount, 2); + CORRADE_VERIFY(info->pSetLayouts); + /* The contents should be copied */ + CORRADE_VERIFY(info->pSetLayouts != layouts); + CORRADE_COMPARE(info->pSetLayouts[0], reinterpret_cast(0xdead)); + CORRADE_COMPARE(info->pSetLayouts[1], reinterpret_cast(0xbeef)); } void PipelineLayoutTest::createInfoConstructNoInit() { @@ -76,6 +95,32 @@ void PipelineLayoutTest::createInfoConstructFromVk() { CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); } +void PipelineLayoutTest::createInfoConstructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +void PipelineLayoutTest::createInfoConstructMove() { + PipelineLayoutCreateInfo a{reinterpret_cast(0xdead), reinterpret_cast(0xbeef)}; + CORRADE_COMPARE(a->setLayoutCount, 2); + CORRADE_VERIFY(a->pSetLayouts); + + PipelineLayoutCreateInfo b = std::move(a); + CORRADE_COMPARE(a->setLayoutCount, 0); + CORRADE_VERIFY(!a->pSetLayouts); + CORRADE_COMPARE(b->setLayoutCount, 2); + CORRADE_VERIFY(b->pSetLayouts); + CORRADE_COMPARE(b->pSetLayouts[1], reinterpret_cast(0xbeef)); + + PipelineLayoutCreateInfo c; + c = std::move(b); + CORRADE_COMPARE(b->setLayoutCount, 0); + CORRADE_VERIFY(!b->pSetLayouts); + CORRADE_COMPARE(c->setLayoutCount, 2); + CORRADE_VERIFY(c->pSetLayouts); + CORRADE_COMPARE(c->pSetLayouts[1], reinterpret_cast(0xbeef)); +} + void PipelineLayoutTest::constructNoCreate() { { PipelineLayout layout{NoCreate}; diff --git a/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp b/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp index 0c5b92a79..e9869929f 100644 --- a/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp +++ b/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp @@ -25,6 +25,7 @@ #include +#include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" #include "Magnum/Vk/PipelineLayoutCreateInfo.h" #include "Magnum/Vk/Result.h" #include "Magnum/Vk/VulkanTester.h" @@ -34,21 +35,24 @@ namespace Magnum { namespace Vk { namespace Test { namespace { struct PipelineLayoutVkTest: VulkanTester { explicit PipelineLayoutVkTest(); - void construct(); + void constructEmpty(); + void constructWithDescriptorSetLayout(); void constructMove(); void wrap(); }; PipelineLayoutVkTest::PipelineLayoutVkTest() { - addTests({&PipelineLayoutVkTest::construct, + addTests({&PipelineLayoutVkTest::constructEmpty, + &PipelineLayoutVkTest::constructWithDescriptorSetLayout, &PipelineLayoutVkTest::constructMove, &PipelineLayoutVkTest::wrap}); } -void PipelineLayoutVkTest::construct() { +void PipelineLayoutVkTest::constructEmpty() { { + /* Rare, but should still work */ PipelineLayout layout{device(), PipelineLayoutCreateInfo{}}; CORRADE_VERIFY(layout.handle()); CORRADE_COMPARE(layout.handleFlags(), HandleFlag::DestroyOnDestruction); @@ -58,6 +62,26 @@ void PipelineLayoutVkTest::construct() { CORRADE_VERIFY(true); } +void PipelineLayoutVkTest::constructWithDescriptorSetLayout() { + { + DescriptorSetLayout descriptorSetLayout1{device(), DescriptorSetLayoutCreateInfo{ + {{15, DescriptorType::UniformBuffer}} + }}; + DescriptorSetLayout descriptorSetLayout2{device(), DescriptorSetLayoutCreateInfo{ + {{1, DescriptorType::CombinedImageSampler}} + }}; + + PipelineLayout layout{device(), PipelineLayoutCreateInfo{ + descriptorSetLayout1, descriptorSetLayout2 + }}; + CORRADE_VERIFY(layout.handle()); + CORRADE_COMPARE(layout.handleFlags(), HandleFlag::DestroyOnDestruction); + } + + /* Shouldn't crash or anything */ + CORRADE_VERIFY(true); +} + void PipelineLayoutVkTest::constructMove() { PipelineLayout a{device(), PipelineLayoutCreateInfo{}}; VkPipelineLayout handle = a.handle(); From 90b1a5a8ea62f09f8ab243ca07b082afc6188979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 12 Mar 2021 18:17:19 +0100 Subject: [PATCH 086/161] Vk: clarify where CreateInfo does a copy of a list/string. Also make the docs a bit terser in a few places. --- src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h | 3 +- src/Magnum/Vk/DeviceCreateInfo.h | 10 +++--- src/Magnum/Vk/FramebufferCreateInfo.h | 3 +- src/Magnum/Vk/InstanceCreateInfo.h | 34 +++++++++++-------- .../Vk/RasterizationPipelineCreateInfo.h | 8 ++--- src/Magnum/Vk/RenderPassCreateInfo.h | 19 ++++++----- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h index dcb62bfb2..b1193db43 100644 --- a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h +++ b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h @@ -405,8 +405,7 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutCreateInfo { * pre-filled in addition to `sType`, everything else is zero-filled: * * - `flags` - * - `bindingCount` to @cpp bindings.size() @ce - * - `pBindings` to a copy of @p bindings + * - `bindingCount` and `pBindings` to a copy of @p bindings * * If any of the @p bindings has @ref DescriptorSetLayoutBinding::flags() * non-empty, a @type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} diff --git a/src/Magnum/Vk/DeviceCreateInfo.h b/src/Magnum/Vk/DeviceCreateInfo.h index 6a73d3a73..f204c13ac 100644 --- a/src/Magnum/Vk/DeviceCreateInfo.h +++ b/src/Magnum/Vk/DeviceCreateInfo.h @@ -175,9 +175,6 @@ class MAGNUM_VK_EXPORT DeviceCreateInfo { * All listed extensions are expected to be supported either globally * or in at least one of the enabled layers, use * @ref ExtensionProperties::isSupported() to check for their presence. - * The function makes copies of string views that are not global or - * null-terminated, use the @link Containers::Literals::operator""_s() @endlink - * literal to prevent that where possible. * * The following @type_vk{DeviceCreateInfo} fields are set by this * function: @@ -186,7 +183,12 @@ class MAGNUM_VK_EXPORT DeviceCreateInfo { * previously by this function plus @cpp extensions.size() @ce * - `pEnabledExtensionNames` to an array containing all extension * strings added previously by this function together with ones - * from @p extensions + * from @p extensions (doing a copy where needed) + * + * @note The function makes copies of string views that are not global + * or null-terminated, use the + * @link Containers::Literals::operator""_s() @endlink + * literal to prevent that where possible. */ DeviceCreateInfo& addEnabledExtensions(Containers::ArrayView extensions) &; /** @overload */ diff --git a/src/Magnum/Vk/FramebufferCreateInfo.h b/src/Magnum/Vk/FramebufferCreateInfo.h index d5dcab5be..a78fc2035 100644 --- a/src/Magnum/Vk/FramebufferCreateInfo.h +++ b/src/Magnum/Vk/FramebufferCreateInfo.h @@ -91,7 +91,8 @@ class MAGNUM_VK_EXPORT FramebufferCreateInfo { * * - `flags` * - `renderPass` - * - `attachmentCount` and `pAttachments` to @p attachments + * - `attachmentCount` and `pAttachments` to a copy of + * @p attachments * - `width`, `height` and `layers` to @p size */ explicit FramebufferCreateInfo(VkRenderPass renderPass, Containers::ArrayView> attachments, const Vector3i& size, Flags flags = {}); diff --git a/src/Magnum/Vk/InstanceCreateInfo.h b/src/Magnum/Vk/InstanceCreateInfo.h index 08b6b17d0..6c92056ea 100644 --- a/src/Magnum/Vk/InstanceCreateInfo.h +++ b/src/Magnum/Vk/InstanceCreateInfo.h @@ -156,16 +156,18 @@ class MAGNUM_VK_EXPORT InstanceCreateInfo { * Use the @ref version() helper to create the @p version value. The * name is @cpp nullptr @ce by default. * - * The function makes copies of string views that are not global or - * null-terminated, use the @link Containers::Literals::operator""_s() @endlink - * literal to prevent that where possible. - * * The following @type_vk{InstanceCreateInfo} fields are set by this * function: * * - `pApplicationInfo` - * - @cpp pApplicationInfo->pApplicationName @ce to @p name + * - @cpp pApplicationInfo->pApplicationName @ce to @p name (a copy + * of it, if needed) * - @cpp pApplicationInfo->applicationVersion @ce to @p version + * + * @note The function makes copies of string views that are not global + * or null-terminated, use the + * @link Containers::Literals::operator""_s() @endlink literal to + * prevent that where possible. */ InstanceCreateInfo& setApplicationInfo(Containers::StringView name, Version version); @@ -179,10 +181,6 @@ class MAGNUM_VK_EXPORT InstanceCreateInfo { * @ref Vk-Instance-command-line "command-line options", it's not * added. * - * The function makes copies of string views that are not global or - * null-terminated, use the @link Containers::Literals::operator""_s() @endlink - * literal to prevent that where possible. - * * The following @type_vk{InstanceCreateInfo} fields are set by this * function: * @@ -190,7 +188,12 @@ class MAGNUM_VK_EXPORT InstanceCreateInfo { * this function plus @cpp layers.size() @ce * - `pEnabledLayerNames` to an array containing all layer strings * added previously by this function together with ones from - * @p layers + * @p layers (doing a copy where needed) + * + * @note The function makes copies of string views that are not global + * or null-terminated, use the + * @link Containers::Literals::operator""_s() @endlink literal to + * prevent that where possible. */ InstanceCreateInfo& addEnabledLayers(Containers::ArrayView layers); /** @overload */ @@ -208,10 +211,6 @@ class MAGNUM_VK_EXPORT InstanceCreateInfo { * @ref Vk-Instance-command-line "command-line options", it's not * added. * - * The function makes copies of string views that are not global or - * null-terminated, use the @link Containers::Literals::operator""_s() @endlink - * literal to prevent that where possible. - * * The following @type_vk{InstanceCreateInfo} fields are set by this * function: * @@ -219,7 +218,12 @@ class MAGNUM_VK_EXPORT InstanceCreateInfo { * previously by this function plus @cpp extensions.size() @ce * - `pEnabledExtensionNames` to an array containing all extension * strings added previously by this function together with ones - * from @p extensions + * from @p extensions (doing a copy where needed) + * + * @note The function makes copies of string views that are not global + * or null-terminated, use the + * @link Containers::Literals::operator""_s() @endlink literal to + * prevent that where possible. */ InstanceCreateInfo& addEnabledExtensions(Containers::ArrayView extensions); /** @overload */ diff --git a/src/Magnum/Vk/RasterizationPipelineCreateInfo.h b/src/Magnum/Vk/RasterizationPipelineCreateInfo.h index 0052641be..fd4d8c3cb 100644 --- a/src/Magnum/Vk/RasterizationPipelineCreateInfo.h +++ b/src/Magnum/Vk/RasterizationPipelineCreateInfo.h @@ -360,10 +360,6 @@ class MAGNUM_VK_EXPORT RasterizationPipelineCreateInfo { * @p subpass uses * @param flags Rasterization pipeline creation flags * - * Note that the @p shaderSet and @p meshLayout structure internals are - * referenced, not copied, and thus have to stay in scope until the - * @ref Pipeline object is created. - * * The following @type_vk{GraphicsPipelineCreateInfo} and substructure * fields are pre-filled in addition to `sType` of all referenced * structures, everything else is zero-filled: @@ -394,6 +390,10 @@ class MAGNUM_VK_EXPORT RasterizationPipelineCreateInfo { * - `renderPass` * - `subpass` * + * @attention Note that the @p shaderSet and @p meshLayout structure + * internals are referenced, not copied, and thus have to stay in + * scope until the @ref Pipeline object is created. + * * You need to call at least @ref setViewport() or specifying * @ref DynamicRasterizationState::Viewport in * @ref setDynamicStates() for a valid setup. diff --git a/src/Magnum/Vk/RenderPassCreateInfo.h b/src/Magnum/Vk/RenderPassCreateInfo.h index 32df3f362..9578eccd8 100644 --- a/src/Magnum/Vk/RenderPassCreateInfo.h +++ b/src/Magnum/Vk/RenderPassCreateInfo.h @@ -570,8 +570,8 @@ class MAGNUM_VK_EXPORT SubpassDescription { * The following @type_vk{SubpassDescription2} fields are set by this * function: * - * - `inputAttachmentCount` to @cpp attachments.size() @ce - * - `pInputAttachments` to a copy of @p attachments + * - `inputAttachmentCount` and `pInputAttachments` to a copy of + * @p attachments */ SubpassDescription& setInputAttachments(Containers::ArrayView attachments) &; /** @overload */ @@ -601,8 +601,8 @@ class MAGNUM_VK_EXPORT SubpassDescription { * The following @type_vk{SubpassDescription2} fields are set by this * function: * - * - `colorAttachmentCount` to @cpp attachments.size() @ce - * - `pColorAttachments` to a copy of @p attachments + * - `colorAttachmentCount` and `pColorAttachments` to a copy of + * @p attachments * - `pResolveAttachments` to a copy of @p resolveAttachments, if * the parameter is non-empty */ @@ -654,7 +654,8 @@ class MAGNUM_VK_EXPORT SubpassDescription { * The following @type_vk{SubpassDescription2} fields are set by this * function: * - * - `pPreserveAttachments` to a copy of @p attachments + * - `preserveAttachmentCount` and `pPreserveAttachments` to a copy + * of @p attachments */ SubpassDescription& setPreserveAttachments(Containers::ArrayView attachments) &; /** @overload */ @@ -994,8 +995,8 @@ class MAGNUM_VK_EXPORT RenderPassCreateInfo { * The following @type_vk{RenderPassCreateInfo2} fields are set by this * function: * - * - `attachmentCount` to @cpp attachments.size() @ce - * - `pAttachments` to a copy of @p attachments + * - `attachmentCount` and `pAttachments` to a copy of + * @p attachments */ RenderPassCreateInfo& setAttachments(Containers::ArrayView attachments); /** @overload */ @@ -1037,8 +1038,8 @@ class MAGNUM_VK_EXPORT RenderPassCreateInfo { * The following @type_vk{RenderPassCreateInfo2} fields are set by this * function: * - * - `dependencyCount` to @cpp dependencies.size() @ce - * - `pDependencies` to a copy of @p dependencies + * - `dependencyCount` and `pDependencies` to a copy of + * @p dependencies */ RenderPassCreateInfo& setDependencies(Containers::ArrayView dependencies); /** @overload */ From 184a7201e7c97698be8d56d661328f948faa61b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 13 Mar 2021 08:28:29 +0100 Subject: [PATCH 087/161] doc: add some more Vulkan links. Also mention that not all tutorials should be taken as golden standards. --- doc/platforms-vk.dox | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/doc/platforms-vk.dox b/doc/platforms-vk.dox index 5a06fa19f..cb0d54dcc 100644 --- a/doc/platforms-vk.dox +++ b/doc/platforms-vk.dox @@ -73,7 +73,17 @@ Build as a static library and supply to CMake via `Vulkan_LIBRARY`: @include libvulkan.cpp -@section platforms-vk-best-practices Vulkan best practices +@section platforms-vk-best-practices Vulkan tutorials and best practices + +@m_class{m-note m-danger} + +@par + Please note that various vendor may suggest mutually incompatible workflows + and what works best for one may not work for another. Certain tutorials and + posts were also written very early on the Vulkan evolution timeline (2016, + 2017) and the understanding of the API, best practices and driver fast + paths may have changed since. If in doubt about efficiency of certain + approach, always consult multiple sources. Khronos wiki: @@ -90,6 +100,11 @@ NVidia tutorials and tips: - [Tips and Tricks: Vulkan Dos and Don’ts](https://developer.nvidia.com/blog/vulkan-dos-donts/) - [Vulkan Device Generated Commands](https://developer.nvidia.com/blog/new-vulkan-device-generated-commands/) +Intel tutorials: + +- [API without Secrets: Introduction to Vulkan](https://software.intel.com/content/www/us/en/develop/articles/api-without-secrets-introduction-to-vulkan-preface.html) + - [Important note about framebuffer creation efficiency](https://github.com/GameTechDev/IntroductionToVulkan/issues/20) + ARM best practices: - [Vulkan Best Practice for Mobile Developers](https://github.com/ARM-software/vulkan_best_practice_for_mobile_developers) @@ -98,6 +113,7 @@ Various useful links: - [Yet another blog explaining Vulkan synchronization](http://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/) - [Writing an efficient Vulkan renderer](https://zeux.io/2020/02/27/writing-an-efficient-vulkan-renderer/) +- [Custom memory allocators](https://rastergrid.com/blog/sw-eng/2021/03/custom-memory-allocators/) */ From d3755b908f4d344473750a062472a8b1c8c68263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 13 Mar 2021 08:33:29 +0100 Subject: [PATCH 088/161] Vk: put the DescriptorType enum into a dedicated header. It's used by many different classes and there's no obvious place where it could live and be always available when needed, so a dedicated header it is. --- doc/snippets/MagnumVk.cpp | 1 + src/Magnum/Vk/CMakeLists.txt | 1 + src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h | 116 +------------ src/Magnum/Vk/DescriptorType.h | 154 ++++++++++++++++++ .../Vk/Test/DescriptorSetLayoutTest.cpp | 1 + .../Vk/Test/DescriptorSetLayoutVkTest.cpp | 1 + src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp | 1 + 7 files changed, 160 insertions(+), 115 deletions(-) create mode 100644 src/Magnum/Vk/DescriptorType.h diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index 8d90b1047..11b64b578 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -40,6 +40,7 @@ #include "Magnum/Vk/CommandPoolCreateInfo.h" #include "Magnum/Vk/ComputePipelineCreateInfo.h" #include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" +#include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/DeviceCreateInfo.h" #include "Magnum/Vk/DeviceFeatures.h" #include "Magnum/Vk/DeviceProperties.h" diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index fcebd1574..5335d956b 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -75,6 +75,7 @@ set(MagnumVk_HEADERS ComputePipelineCreateInfo.h DescriptorSetLayout.h DescriptorSetLayoutCreateInfo.h + DescriptorType.h Device.h DeviceCreateInfo.h DeviceFeatures.h diff --git a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h index b1193db43..932098d0e 100644 --- a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h +++ b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Vk::DescriptorSetLayoutCreateInfo, @ref Magnum::Vk::DescriptorSetLayoutBinding, enum @ref Magnum::Vk::DescriptorType + * @brief Class @ref Magnum::Vk::DescriptorSetLayoutCreateInfo, @ref Magnum::Vk::DescriptorSetLayoutBinding * @m_since_latest */ @@ -48,120 +48,6 @@ namespace Magnum { namespace Vk { -/** -@brief Descriptor type -@m_since_latest - -Wraps @type_vk_keyword{DescriptorType}. -@see @ref DescriptorSetLayoutBinding -@m_enum_values_as_keywords -*/ -enum class DescriptorType: Int { - /** - * @ref Sampler. - * - * @see @ref DescriptorType::CombinedImageSampler - */ - Sampler = VK_DESCRIPTOR_TYPE_SAMPLER, - - /** - * @ref Sampler combined with an @ref Image. - * - * @m_class{m-note m-success} - * - * @par - * On some implementations it may be more efficient to sample from an - * a combined image sampler than a separate - * @ref DescriptorType::Sampler and @ref DescriptorType::SampledImage. - * - * The image is expected to have been created with @ref ImageUsage::Sampled - * and be in either @ref ImageLayout::General or - * @ref ImageLayout::ShaderReadOnly. - */ - CombinedImageSampler = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - - /** - * Sampled @ref Image. - * - * The image is expected to have been created with @ref ImageUsage::Sampled - * and be in either @ref ImageLayout::General or - * @ref ImageLayout::ShaderReadOnly. - * @see @ref DescriptorType::CombinedImageSampler - */ - SampledImage = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, - - /** - * Storage @ref Image. - * - * The image is expected to have been created with @ref ImageUsage::Storage - * and be in @ref ImageLayout::General. - */ - StorageImage = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, - - /** - * Uniform texel buffer view. - * - * The buffer is expected to have been created with - * @ref BufferUsage::UniformTexelBuffer. - */ - UniformTexelBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - - /** - * Storage texel buffer view. - * - * The buffer is expected to have been created with - * @ref BufferUsage::StorageTexelBuffer. - */ - StorageTexelBuffer = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, - - /** - * Uniform @ref Buffer. - * - * The buffer is expected to have been created with - * @ref BufferUsage::UniformBuffer. - */ - UniformBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - - /** - * Storage @ref Buffer. - * - * The buffer is expected to have been created with - * @ref BufferUsage::StorageBuffer. - */ - StorageBuffer = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, - - /** - * Uniform @ref Buffer with a dynamic offset. - * - * The buffer is expected to have been created with - * @ref BufferUsage::UniformBuffer. - */ - UniformBufferDynamic = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - - /** - * Storage @ref Buffer with a dynamic offset. - * - * The buffer is expected to have been created with - * @ref BufferUsage::StorageBuffer. - */ - StorageBufferDynamic = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, - - /** - * Input @ref Image attachment. - * - * The image is expected to have been created with - * @ref ImageUsage::InputAttachment and be in @ref ImageLayout::General. - */ - InputAttachment = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, - - /** - * Acceleration structure. - * - * @requires_vk_feature @ref DeviceFeature::AccelerationStructure - */ - AccelerationStructure = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR -}; - /** @brief Descriptor set layout binding @m_since_latest diff --git a/src/Magnum/Vk/DescriptorType.h b/src/Magnum/Vk/DescriptorType.h new file mode 100644 index 000000000..9022eff01 --- /dev/null +++ b/src/Magnum/Vk/DescriptorType.h @@ -0,0 +1,154 @@ +#ifndef Magnum_Vk_DescriptorType_h +#define Magnum_Vk_DescriptorType_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 Enum @ref Magnum::Vk::DescriptorType + * @m_since_latest + */ + +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Descriptor type +@m_since_latest + +Wraps @type_vk_keyword{DescriptorType}. +@see @ref DescriptorSetLayoutBinding +@m_enum_values_as_keywords +*/ +enum class DescriptorType: Int { + /** + * @ref Sampler. + * + * @see @ref DescriptorType::CombinedImageSampler + */ + Sampler = VK_DESCRIPTOR_TYPE_SAMPLER, + + /** + * @ref Sampler combined with an @ref Image. + * + * @m_class{m-note m-success} + * + * @par + * On some implementations it may be more efficient to sample from an + * a combined image sampler than a separate + * @ref DescriptorType::Sampler and @ref DescriptorType::SampledImage. + * + * The image is expected to have been created with @ref ImageUsage::Sampled + * and be in either @ref ImageLayout::General or + * @ref ImageLayout::ShaderReadOnly. + */ + CombinedImageSampler = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + + /** + * Sampled @ref Image. + * + * The image is expected to have been created with @ref ImageUsage::Sampled + * and be in either @ref ImageLayout::General or + * @ref ImageLayout::ShaderReadOnly. + * @see @ref DescriptorType::CombinedImageSampler + */ + SampledImage = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + + /** + * Storage @ref Image. + * + * The image is expected to have been created with @ref ImageUsage::Storage + * and be in @ref ImageLayout::General. + */ + StorageImage = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, + + /** + * Uniform texel buffer view. + * + * The buffer is expected to have been created with + * @ref BufferUsage::UniformTexelBuffer. + */ + UniformTexelBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + + /** + * Storage texel buffer view. + * + * The buffer is expected to have been created with + * @ref BufferUsage::StorageTexelBuffer. + */ + StorageTexelBuffer = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + + /** + * Uniform @ref Buffer. + * + * The buffer is expected to have been created with + * @ref BufferUsage::UniformBuffer. + */ + UniformBuffer = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + + /** + * Storage @ref Buffer. + * + * The buffer is expected to have been created with + * @ref BufferUsage::StorageBuffer. + */ + StorageBuffer = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + + /** + * Uniform @ref Buffer with a dynamic offset. + * + * The buffer is expected to have been created with + * @ref BufferUsage::UniformBuffer. + */ + UniformBufferDynamic = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + + /** + * Storage @ref Buffer with a dynamic offset. + * + * The buffer is expected to have been created with + * @ref BufferUsage::StorageBuffer. + */ + StorageBufferDynamic = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + + /** + * Input @ref Image attachment. + * + * The image is expected to have been created with + * @ref ImageUsage::InputAttachment and be in @ref ImageLayout::General. + */ + InputAttachment = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, + + /** + * Acceleration structure. + * + * @requires_vk_feature @ref DeviceFeature::AccelerationStructure + */ + AccelerationStructure = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR +}; + +}} + +#endif diff --git a/src/Magnum/Vk/Test/DescriptorSetLayoutTest.cpp b/src/Magnum/Vk/Test/DescriptorSetLayoutTest.cpp index 750d41128..db9aa3af9 100644 --- a/src/Magnum/Vk/Test/DescriptorSetLayoutTest.cpp +++ b/src/Magnum/Vk/Test/DescriptorSetLayoutTest.cpp @@ -27,6 +27,7 @@ #include #include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" +#include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/Shader.h" namespace Magnum { namespace Vk { namespace Test { namespace { diff --git a/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp b/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp index ca463eccc..7a6f2e4d6 100644 --- a/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp +++ b/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp @@ -26,6 +26,7 @@ #include #include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" +#include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/Result.h" #include "Magnum/Vk/VulkanTester.h" diff --git a/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp b/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp index e9869929f..949fb4f47 100644 --- a/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp +++ b/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp @@ -26,6 +26,7 @@ #include #include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" +#include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/PipelineLayoutCreateInfo.h" #include "Magnum/Vk/Result.h" #include "Magnum/Vk/VulkanTester.h" From 9d648ce94933888f9740732782db8013836653fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 13 Mar 2021 08:34:32 +0100 Subject: [PATCH 089/161] Vk: these includes aren't needed here. Feels like copypaste leftovers. A lot of them. --- src/Magnum/Vk/FenceCreateInfo.h | 1 - src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp | 2 -- src/Magnum/Vk/Test/FenceVkTest.cpp | 2 -- src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp | 2 -- src/Magnum/Vk/Test/SamplerVkTest.cpp | 2 -- 5 files changed, 9 deletions(-) diff --git a/src/Magnum/Vk/FenceCreateInfo.h b/src/Magnum/Vk/FenceCreateInfo.h index b3286c8f9..761f5c4e2 100644 --- a/src/Magnum/Vk/FenceCreateInfo.h +++ b/src/Magnum/Vk/FenceCreateInfo.h @@ -30,7 +30,6 @@ * @m_since_latest */ -#include #include #include "Magnum/Magnum.h" diff --git a/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp b/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp index 7a6f2e4d6..3754d2447 100644 --- a/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp +++ b/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp @@ -23,8 +23,6 @@ DEALINGS IN THE SOFTWARE. */ -#include - #include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" #include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/Result.h" diff --git a/src/Magnum/Vk/Test/FenceVkTest.cpp b/src/Magnum/Vk/Test/FenceVkTest.cpp index 4a9eafe2b..e83499bf7 100644 --- a/src/Magnum/Vk/Test/FenceVkTest.cpp +++ b/src/Magnum/Vk/Test/FenceVkTest.cpp @@ -23,8 +23,6 @@ DEALINGS IN THE SOFTWARE. */ -#include - #include "Magnum/Vk/FenceCreateInfo.h" #include "Magnum/Vk/Result.h" #include "Magnum/Vk/VulkanTester.h" diff --git a/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp b/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp index 949fb4f47..deadde422 100644 --- a/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp +++ b/src/Magnum/Vk/Test/PipelineLayoutVkTest.cpp @@ -23,8 +23,6 @@ DEALINGS IN THE SOFTWARE. */ -#include - #include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" #include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/PipelineLayoutCreateInfo.h" diff --git a/src/Magnum/Vk/Test/SamplerVkTest.cpp b/src/Magnum/Vk/Test/SamplerVkTest.cpp index c2abac8dd..292297896 100644 --- a/src/Magnum/Vk/Test/SamplerVkTest.cpp +++ b/src/Magnum/Vk/Test/SamplerVkTest.cpp @@ -23,8 +23,6 @@ DEALINGS IN THE SOFTWARE. */ -#include - #include "Magnum/Vk/SamplerCreateInfo.h" #include "Magnum/Vk/Result.h" #include "Magnum/Vk/VulkanTester.h" From afb5c9f4a23f6e0260cddad234b40cd66971cd4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 13 Mar 2021 09:13:59 +0100 Subject: [PATCH 090/161] Vk: interestingly enough, DescriptorSetLayout can be empty. I wanted to add asserts for this but seems like it's allowed. Adding tests for that instead, then. --- src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h | 10 +++---- .../Vk/Test/DescriptorSetLayoutVkTest.cpp | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h index 932098d0e..a7cd9ec9b 100644 --- a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h +++ b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h @@ -134,8 +134,8 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { * binding in a shader * @param descriptorType Descriptor type * @param descriptorCount Number of descriptors contained in the - * binding. Has to be at least @cpp 1 @ce. If the shader binding - * is not an array, use @cpp 1 @ce. + * binding. If the shader binding is not an array, use @cpp 1 @ce, + * zero is allowed as well. * @param stages Shader stages that access the binding. * Use @cpp ~Vk::ShaderStages{} @ce to specify that all stages * may access the binding. @@ -163,7 +163,7 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { * @param descriptorType Descriptor type. Should be either * @ref DescriptorType::Sampler or * @ref DescriptorType::CombinedImageSampler. - * @param immutableSamplers Immutable samplers + * @param immutableSamplers Immutable samplers. Allowed to be empty. * @param stages Shader stages that access the binding. * Use @cpp ~Vk::ShaderStages{} @ce to specify that all stages * may access the binding. @@ -283,8 +283,8 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutCreateInfo { /** * @brief Constructor - * @param bindings Descriptor set layout bindings. At least one - * binding has to be present. + * @param bindings Descriptor set layout bindings. Allowed to be + * empty. * @param flags Descriptor set layout creation flags * * The following @type_vk{DescriptorSetLayoutCreateInfo} fields are diff --git a/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp b/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp index 3754d2447..23214ec8c 100644 --- a/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp +++ b/src/Magnum/Vk/Test/DescriptorSetLayoutVkTest.cpp @@ -34,6 +34,8 @@ struct DescriptorSetLayoutVkTest: VulkanTester { explicit DescriptorSetLayoutVkTest(); void construct(); + void constructEmpty(); + void constructEmptyBinding(); void constructMove(); void wrap(); @@ -41,6 +43,8 @@ struct DescriptorSetLayoutVkTest: VulkanTester { DescriptorSetLayoutVkTest::DescriptorSetLayoutVkTest() { addTests({&DescriptorSetLayoutVkTest::construct, + &DescriptorSetLayoutVkTest::constructEmpty, + &DescriptorSetLayoutVkTest::constructEmptyBinding, &DescriptorSetLayoutVkTest::constructMove, &DescriptorSetLayoutVkTest::wrap}); @@ -59,6 +63,32 @@ void DescriptorSetLayoutVkTest::construct() { CORRADE_VERIFY(true); } +void DescriptorSetLayoutVkTest::constructEmpty() { + { + /* Although rather weird, the spec allows this */ + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{}}; + CORRADE_VERIFY(layout.handle()); + CORRADE_COMPARE(layout.handleFlags(), HandleFlag::DestroyOnDestruction); + } + + /* Shouldn't crash or anything */ + CORRADE_VERIFY(true); +} + +void DescriptorSetLayoutVkTest::constructEmptyBinding() { + { + /* Also weird, but the spec *also* allows this */ + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{ + {{15, DescriptorType::UniformBuffer, 0}} + }}; + CORRADE_VERIFY(layout.handle()); + CORRADE_COMPARE(layout.handleFlags(), HandleFlag::DestroyOnDestruction); + } + + /* Shouldn't crash or anything */ + CORRADE_VERIFY(true); +} + void DescriptorSetLayoutVkTest::constructMove() { DescriptorSetLayout a{device(), DescriptorSetLayoutCreateInfo{ {{15, DescriptorType::UniformBuffer}} From b533599dd9ef703e0daddbe70c6a528f8225811b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 13 Mar 2021 09:38:47 +0100 Subject: [PATCH 091/161] Vk: add debug output for DescriptorType. Will need it in one assert. --- src/Magnum/Vk/CMakeLists.txt | 1 + src/Magnum/Vk/DescriptorType.cpp | 58 +++++++++++++++++++++++ src/Magnum/Vk/DescriptorType.h | 7 +++ src/Magnum/Vk/Test/CMakeLists.txt | 2 + src/Magnum/Vk/Test/DescriptorTypeTest.cpp | 52 ++++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 src/Magnum/Vk/DescriptorType.cpp create mode 100644 src/Magnum/Vk/Test/DescriptorTypeTest.cpp diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 5335d956b..95abbc271 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -30,6 +30,7 @@ set(MagnumVk_SRCS CommandBuffer.cpp CommandPool.cpp DescriptorSetLayout.cpp + DescriptorType.cpp Extensions.cpp Fence.cpp Framebuffer.cpp diff --git a/src/Magnum/Vk/DescriptorType.cpp b/src/Magnum/Vk/DescriptorType.cpp new file mode 100644 index 000000000..5b0080792 --- /dev/null +++ b/src/Magnum/Vk/DescriptorType.cpp @@ -0,0 +1,58 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 "DescriptorType.h" + +#include + +namespace Magnum { namespace Vk { + +Debug& operator<<(Debug& debug, const DescriptorType value) { + debug << "Vk::DescriptorType" << Debug::nospace; + + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Vk::DescriptorType::value: return debug << "::" << Debug::nospace << #value; + _c(Sampler) + _c(CombinedImageSampler) + _c(SampledImage) + _c(StorageImage) + _c(UniformTexelBuffer) + _c(StorageTexelBuffer) + _c(UniformBuffer) + _c(StorageBuffer) + _c(UniformBufferDynamic) + _c(StorageBufferDynamic) + _c(InputAttachment) + _c(AccelerationStructure) + #undef _c + /* LCOV_EXCL_STOP */ + } + + /* Vulkan docs have the values in decimal, so not converting to hex */ + return debug << "(" << Debug::nospace << Int(value) << Debug::nospace << ")"; +} + +}} diff --git a/src/Magnum/Vk/DescriptorType.h b/src/Magnum/Vk/DescriptorType.h index 9022eff01..494fe641e 100644 --- a/src/Magnum/Vk/DescriptorType.h +++ b/src/Magnum/Vk/DescriptorType.h @@ -30,6 +30,7 @@ * @m_since_latest */ +#include "Magnum/Vk/visibility.h" #include "Magnum/Vk/Vk.h" #include "Magnum/Vk/Vulkan.h" @@ -149,6 +150,12 @@ enum class DescriptorType: Int { AccelerationStructure = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR }; +/** +@debugoperatorenum{DescriptorType} +@m_since_latest +*/ +MAGNUM_VK_EXPORT Debug& operator<<(Debug& debug, DescriptorType value); + }} #endif diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index 04ca80668..5c40346b3 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -28,6 +28,7 @@ corrade_add_test(VkBufferTest BufferTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkCommandBufferTest CommandBufferTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDescriptorSetLayoutTest DescriptorSetLayoutTest.cpp LIBRARIES MagnumVk) +corrade_add_test(VkDescriptorTypeTest DescriptorTypeTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceTest DeviceTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDevicePropertiesTest DevicePropertiesTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceFeaturesTest DeviceFeaturesTest.cpp LIBRARIES MagnumVk) @@ -131,6 +132,7 @@ set_target_properties( VkCommandBufferTest VkCommandPoolTest VkDescriptorSetLayoutTest + VkDescriptorTypeTest VkDeviceTest VkDeviceFeaturesTest VkDevicePropertiesTest diff --git a/src/Magnum/Vk/Test/DescriptorTypeTest.cpp b/src/Magnum/Vk/Test/DescriptorTypeTest.cpp new file mode 100644 index 000000000..4b1f89f8e --- /dev/null +++ b/src/Magnum/Vk/Test/DescriptorTypeTest.cpp @@ -0,0 +1,52 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 +#include +#include + +#include "Magnum/Vk/DescriptorType.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DescriptorTypeTest: TestSuite::Tester { + explicit DescriptorTypeTest(); + + void debug(); +}; + +DescriptorTypeTest::DescriptorTypeTest() { + addTests({&DescriptorTypeTest::debug}); +} + +void DescriptorTypeTest::debug() { + std::ostringstream out; + Debug{&out} << DescriptorType::InputAttachment << DescriptorType(-10007655); + CORRADE_COMPARE(out.str(), "Vk::DescriptorType::InputAttachment Vk::DescriptorType(-10007655)\n"); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DescriptorTypeTest) From c045d1666c3e9b099d9e0752aa838877d92e6e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 13 Mar 2021 10:11:49 +0100 Subject: [PATCH 092/161] Vk: add a DescriptorPool wrapper. --- doc/snippets/MagnumVk.cpp | 16 ++ doc/vulkan-mapping.dox | 10 +- src/Magnum/Vk/CMakeLists.txt | 3 + src/Magnum/Vk/DescriptorPool.cpp | 131 +++++++++++++ src/Magnum/Vk/DescriptorPool.h | 144 ++++++++++++++ src/Magnum/Vk/DescriptorPoolCreateInfo.h | 183 ++++++++++++++++++ src/Magnum/Vk/DescriptorSetLayout.h | 2 +- src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h | 13 +- src/Magnum/Vk/DescriptorType.h | 2 +- src/Magnum/Vk/Test/CMakeLists.txt | 4 + src/Magnum/Vk/Test/DescriptorPoolTest.cpp | 183 ++++++++++++++++++ src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp | 103 ++++++++++ src/Magnum/Vk/Vk.h | 2 + 13 files changed, 788 insertions(+), 8 deletions(-) create mode 100644 src/Magnum/Vk/DescriptorPool.cpp create mode 100644 src/Magnum/Vk/DescriptorPool.h create mode 100644 src/Magnum/Vk/DescriptorPoolCreateInfo.h create mode 100644 src/Magnum/Vk/Test/DescriptorPoolTest.cpp create mode 100644 src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index 11b64b578..a3c8c966e 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -39,6 +39,7 @@ #include "Magnum/Vk/CommandBuffer.h" #include "Magnum/Vk/CommandPoolCreateInfo.h" #include "Magnum/Vk/ComputePipelineCreateInfo.h" +#include "Magnum/Vk/DescriptorPoolCreateInfo.h" #include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" #include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/DeviceCreateInfo.h" @@ -314,6 +315,21 @@ fence.wait(); /* [CommandBuffer-usage-submit] */ } +{ +Vk::Device device{NoCreate}; +/* The include should be a no-op here since it was already included above */ +/* [DescriptorPool-creation] */ +#include + +DOXYGEN_IGNORE() + +Vk::DescriptorPool pool{device, Vk::DescriptorPoolCreateInfo{8, { + {Vk::DescriptorType::UniformBuffer, 24}, + {Vk::DescriptorType::CombinedImageSampler, 16} +}}}; +/* [DescriptorPool-creation] */ +} + { Vk::Device device{NoCreate}; /* The include should be a no-op here since it was already included above */ diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index 55dde6ffb..0a73aa051 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -58,7 +58,7 @@ Vulkan handle | Matching API @type_vk{DeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR** | | @type_vk{DebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | | -@type_vk{DescriptorPool} | | +@type_vk{DescriptorPool} | @ref DescriptorPool @type_vk{DescriptorSet} | | @type_vk{DescriptorSetLayout} | @ref DescriptorSetLayout @type_vk{DescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @@ -190,7 +190,7 @@ Vulkan function | Matching API @fn_vk{CreateDebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | | @fn_vk{CreateDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @fn_vk{DestroyDebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | | @fn_vk{CreateDeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR**, \n @fn_vk{DestroyDeferredOperationKHR} @m_class{m-label m-flat m-warning} **KHR** | | -@fn_vk{CreateDescriptorPool}, \n @fn_vk{DestroyDescriptorPool} | | +@fn_vk{CreateDescriptorPool}, \n @fn_vk{DestroyDescriptorPool} | @ref DescriptorPool constructor and destructor @fn_vk{CreateDescriptorSetLayout}, \n @fn_vk{DestroyDescriptorSetLayout} | @ref DescriptorSetLayout constructor and destructor @fn_vk{CreateDescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1**, \n @fn_vk{DestroyDescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @fn_vk{CreateDevice}, \n @fn_vk{DestroyDevice} | @ref Device constructor and destructor @@ -463,8 +463,8 @@ Vulkan structure | Matching API @type_vk{DebugUtilsObjectTagInfoEXT} @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DescriptorBufferInfo} | | @type_vk{DescriptorImageInfo} | | -@type_vk{DescriptorPoolCreateInfo} | | -@type_vk{DescriptorPoolSize} | | +@type_vk{DescriptorPoolCreateInfo} | @ref DescriptorPoolCreateInfo +@type_vk{DescriptorPoolSize} | @ref DescriptorPoolCreateInfo @type_vk{DescriptorSetAllocateInfo} | | @type_vk{DescriptorSetLayoutBinding} | @ref DescriptorSetLayoutBinding @type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} @m_class{m-label m-flqat m-success} **EXT, 1.2** | @ref DescriptorSetLayoutCreateInfo @@ -826,7 +826,7 @@ Vulkan enum | Matching API @type_vk{DebugUtilsMessageSeverityFlagBitsEXT} @m_class{m-label m-flat m-warning} **EXT**, \n @type_vk{DebugUtilsMessageTypeFlagsEXT} @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DependencyFlagBits}, \n @type_vk{DependencyFlags} | @ref DependencyFlag, \n @ref DependencyFlags @type_vk{DescriptorBindingFlagBits} @m_class{m-label m-flat m-success} **EXT, 1.2**, \n @type_vk{DescriptorBindingFlags} @m_class{m-label m-flat m-success} **EXT, 1.2** | @ref DescriptorSetLayoutBinding::Flag, \n @ref DescriptorSetLayoutBinding::Flags -@type_vk{DescriptorPoolCreateFlagBits}, \n @type_vk{DescriptorPoolCreateFlags} | | +@type_vk{DescriptorPoolCreateFlagBits}, \n @type_vk{DescriptorPoolCreateFlags} | @ref DescriptorPoolCreateInfo::Flag, \n @ref DescriptorPoolCreateInfo::Flags @type_vk{DescriptorSetLayoutCreateFlagBits}, \n @type_vk{DescriptorSetLayoutCreateFlags} | @ref DescriptorSetLayoutCreateInfo::Flag, \n @ref DescriptorSetLayoutCreateInfo::Flags @type_vk{DescriptorUpdateTemplateType} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorType} | @ref DescriptorType diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index 95abbc271..f4d189ccb 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -48,6 +48,7 @@ set(MagnumVk_SRCS set(MagnumVk_GracefulAssert_SRCS Buffer.cpp + DescriptorPool.cpp Device.cpp DeviceProperties.cpp DeviceFeatures.cpp @@ -74,6 +75,8 @@ set(MagnumVk_HEADERS CommandPool.h CommandPoolCreateInfo.h ComputePipelineCreateInfo.h + DescriptorPool.h + DescriptorPoolCreateInfo.h DescriptorSetLayout.h DescriptorSetLayoutCreateInfo.h DescriptorType.h diff --git a/src/Magnum/Vk/DescriptorPool.cpp b/src/Magnum/Vk/DescriptorPool.cpp new file mode 100644 index 000000000..d9a1616c1 --- /dev/null +++ b/src/Magnum/Vk/DescriptorPool.cpp @@ -0,0 +1,131 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 "DescriptorPool.h" +#include "DescriptorPoolCreateInfo.h" + +#include + +#include "Magnum/Vk/Assert.h" +#include "Magnum/Vk/DescriptorType.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/Result.h" + +namespace Magnum { namespace Vk { + +DescriptorPoolCreateInfo::DescriptorPoolCreateInfo(const UnsignedInt maxSets, const Containers::ArrayView> poolSizes, const Flags flags): _info{} { + CORRADE_ASSERT(maxSets, + "Vk::DescriptorPoolCreateInfo: there has to be at least one set", ); + CORRADE_ASSERT(poolSizes, + "Vk::DescriptorPoolCreateInfo: there has to be at least one pool", ); + + Containers::ArrayView poolSizesCopy; + _data = Containers::ArrayTuple{ + {Containers::NoInit, poolSizes.size(), poolSizesCopy} + }; + for(std::size_t i = 0; i != poolSizes.size(); ++i) { + CORRADE_ASSERT(poolSizes[i].second, + "Vk::DescriptorPoolCreateInfo: pool" << i << "of" << poolSizes[i].first << "has no descriptors", ); + poolSizesCopy[i].type = VkDescriptorType(poolSizes[i].first); + poolSizesCopy[i].descriptorCount = poolSizes[i].second; + } + + _info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + _info.flags = VkDescriptorPoolCreateFlags(flags); + _info.maxSets = maxSets; + _info.poolSizeCount = poolSizesCopy.size(); + _info.pPoolSizes = poolSizesCopy; +} + +DescriptorPoolCreateInfo::DescriptorPoolCreateInfo(const UnsignedInt maxSets, const std::initializer_list> poolSizes, const Flags flags): DescriptorPoolCreateInfo{maxSets, Containers::arrayView(poolSizes), flags} {} + +DescriptorPoolCreateInfo::DescriptorPoolCreateInfo(NoInitT) noexcept {} + +DescriptorPoolCreateInfo::DescriptorPoolCreateInfo(const VkDescriptorPoolCreateInfo& info): + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _info(info) {} + +DescriptorPoolCreateInfo::DescriptorPoolCreateInfo(DescriptorPoolCreateInfo&& other) noexcept: + /* Can't use {} with GCC 4.8 here because it tries to initialize the first + member instead of doing a copy */ + _info(other._info), + _data{std::move(other._data)} +{ + /* Ensure the previous instance doesn't reference state that's now ours */ + /** @todo this is now more like a destructible move, do it more selectively + and clear only what's really ours and not external? */ + other._info.pNext = nullptr; + other._info.poolSizeCount = 0; + other._info.pPoolSizes = nullptr; +} + +DescriptorPoolCreateInfo::~DescriptorPoolCreateInfo() = default; + +DescriptorPoolCreateInfo& DescriptorPoolCreateInfo::operator=(DescriptorPoolCreateInfo&& other) noexcept { + using std::swap; + swap(other._info, _info); + swap(other._data, _data); + return *this; +} + +DescriptorPool DescriptorPool::wrap(Device& device, const VkDescriptorPool handle, const HandleFlags flags) { + DescriptorPool out{NoCreate}; + out._device = &device; + out._handle = handle; + out._flags = flags; + return out; +} + +DescriptorPool::DescriptorPool(Device& device, const DescriptorPoolCreateInfo& info): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} { + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateDescriptorPool(device, info, nullptr, &_handle)); +} + +DescriptorPool::DescriptorPool(NoCreateT): _device{}, _handle{} {} + +DescriptorPool::DescriptorPool(DescriptorPool&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} { + other._handle = {}; +} + +DescriptorPool::~DescriptorPool() { + if(_handle && (_flags & HandleFlag::DestroyOnDestruction)) + (**_device).DestroyDescriptorPool(*_device, _handle, nullptr); +} + +DescriptorPool& DescriptorPool::operator=(DescriptorPool&& other) noexcept { + using std::swap; + swap(other._device, _device); + swap(other._handle, _handle); + swap(other._flags, _flags); + return *this; +} + +VkDescriptorPool DescriptorPool::release() { + const VkDescriptorPool handle = _handle; + _handle = {}; + return handle; +} + +}} diff --git a/src/Magnum/Vk/DescriptorPool.h b/src/Magnum/Vk/DescriptorPool.h new file mode 100644 index 000000000..7976b435e --- /dev/null +++ b/src/Magnum/Vk/DescriptorPool.h @@ -0,0 +1,144 @@ +#ifndef Magnum_Vk_DescriptorPool_h +#define Magnum_Vk_DescriptorPool_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Vk::DescriptorPool + * @m_since_latest + */ + +#include "Magnum/Tags.h" +#include "Magnum/Vk/Handle.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Descriptor pool +@m_since_latest + +Wraps @type_vk_keyword{DescriptorPool}, which is used for allocating descriptor +sets. + +@section Vk-DescriptorPool-creation Descriptor pool creation + +The @ref DescriptorPoolCreateInfo class takes a maximum number of descriptor +sets that can be allocated from a pool and then a list of total available +descriptor counts for desired @ref DescriptorType "DescriptorTypes". The +following snippet creates a pool allowing to allocate at most 8 descriptor sets +with 24 sampler bindings and 16 uniform bindings: + +@snippet MagnumVk.cpp DescriptorPool-creation +*/ +class MAGNUM_VK_EXPORT DescriptorPool { + public: + /** + * @brief Wrap existing Vulkan handle + * @param device Vulkan device the descriptor pool is + * created on + * @param handle The @type_vk{DescriptorPool} handle + * @param flags Handle flags + * + * The @p handle is expected to be originating from @p device. Unlike + * a descriptor pool created using a constructor, the Vulkan descriptor + * pool is by default not deleted on destruction, use @p flags for + * different behavior. + * @see @ref release() + */ + static DescriptorPool wrap(Device& device, VkDescriptorPool handle, HandleFlags flags = {}); + + /** + * @brief Constructor + * @param device Vulkan device to create the descriptor pool on + * @param info Descriptor pool creation info + * + * @see @fn_vk_keyword{CreateDescriptorPool} + */ + explicit DescriptorPool(Device& device, const DescriptorPoolCreateInfo& info); + + /** + * @brief Construct without creating the fence + * + * The constructed instance is equivalent to moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + */ + explicit DescriptorPool(NoCreateT); + + /** @brief Copying is not allowed */ + DescriptorPool(const DescriptorPool&) = delete; + + /** @brief Move constructor */ + DescriptorPool(DescriptorPool&& other) noexcept; + + /** + * @brief Destructor + * + * Destroys associated @type_vk{DescriptorPool} handle, unless the + * instance was created using @ref wrap() without + * @ref HandleFlag::DestroyOnDestruction specified. + * @see @fn_vk_keyword{DestroyDescriptorPool}, @ref release() + */ + ~DescriptorPool(); + + /** @brief Copying is not allowed */ + DescriptorPool& operator=(const DescriptorPool&) = delete; + + /** @brief Move assignment */ + DescriptorPool& operator=(DescriptorPool&& other) noexcept; + + /** @brief Underlying @type_vk{DescriptorPool} handle */ + VkDescriptorPool handle() { return _handle; } + /** @overload */ + operator VkDescriptorPool() { return _handle; } + + /** @brief Handle flags */ + HandleFlags handleFlags() const { return _flags; } + + /** + * @brief Release the underlying Vulkan descriptor pool + * + * Releases ownership of the Vulkan descriptor pool and returns its + * handle so @fn_vk{DestroyDescriptorPool} is not called on + * destruction. The internal state is then equivalent to moved-from + * state. + * @see @ref wrap() + */ + VkDescriptorPool release(); + + private: + /* Can't be a reference because of the NoCreate constructor */ + Device* _device; + + VkDescriptorPool _handle; + HandleFlags _flags; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/DescriptorPoolCreateInfo.h b/src/Magnum/Vk/DescriptorPoolCreateInfo.h new file mode 100644 index 000000000..3d84c3934 --- /dev/null +++ b/src/Magnum/Vk/DescriptorPoolCreateInfo.h @@ -0,0 +1,183 @@ +#ifndef Magnum_Vk_DescriptorPoolCreateInfo_h +#define Magnum_Vk_DescriptorPoolCreateInfo_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Vk::DescriptorPoolCreateInfo + * @m_since_latest + */ + +#include +#include +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Tags.h" +#include "Magnum/Vk/visibility.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" + +namespace Magnum { namespace Vk { + +/** +@brief Descriptor pool creation info +@m_since_latest + +Wraps a @type_vk_keyword{DescriptorPoolCreateInfo} and the nested +@type_vk_keyword{DescriptorPoolSize} structures. See +@ref Vk-DescriptorPool-creation "Descriptor pool creation" for usage +information. +*/ +class MAGNUM_VK_EXPORT DescriptorPoolCreateInfo { + public: + /** + * @brief Descriptor pool creation flag + * + * Wraps @type_vk_keyword{DescriptorPoolCreateFlagBits}. + * @see @ref Flags, @ref DescriptorPoolCreateInfo() + * @m_enum_values_as_keywords + */ + enum class Flag: UnsignedInt { + /** + * Allow individual descriptor sets to be freed instead of just the + * whole pool. + * @todoc reference relevant functions once they exist + * + * @m_class{m-note m-success} + * + * @par + * Not using this flag may help the driver to use simpler + * per-pool allocators instead of per-set. Without this flag + * set, descriptor pool fragmentation can't occur. + */ + FreeDescriptorSet = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + + /** + * Descriptor sets allocated from this pool can use bindings with + * the @ref DescriptorSetLayoutBinding::Flag::UpdateAfterBind set. + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingSampledImageUpdateAfterBind + * if used on a @ref DescriptorType::CombinedImageSampler / + * @relativeref{DescriptorType,SampledImage} + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingStorageImageUpdateAfterBind + * if used on a @ref DescriptorType::StorageImage + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingUniformTexelBufferUpdateAfterBind + * if used on a @ref DescriptorType::UniformTexelBuffer + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingStorageTexelBufferUpdateAfterBind + * if used on a @ref DescriptorType::StorageTexelBuffer + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind + * if used on a @ref DescriptorType::UniformBuffer / + * @relativeref{DescriptorType,UniformBufferDynamic} + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingStorageBufferUpdateAfterBind + * if used on a @ref DescriptorType::StorageBuffer / + * @relativeref{DescriptorType,StorageBufferDynamic} + */ + UpdateAfterBind = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT + }; + + /** + * @brief DescriptorPool creation flags + * + * Type-safe wrapper for @type_vk_keyword{DescriptorPoolCreateFlags}. + * @see @ref DescriptorPoolCreateInfo() + */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param maxSets Maximum count of descriptor sets that can be + * allocated from this pool. Has to be at least one. + * @param poolSizes Pool sizes for each descriptor type. There has + * to be at least one, and pool sizes can't be zero. + * @param flags DescriptorPool creation flags + * + * The following @type_vk{DescriptorPoolCreateInfo} fields are + * pre-filled in addition to `sType`, everything else is zero-filled: + * + * - `flags` + * - `maxSets` + * - `poolSizeCount` and `pPoolSizes` to @p poolSizes converted to + * a list of @type_vk{DescriptorPoolSize} structures + */ + explicit DescriptorPoolCreateInfo(UnsignedInt maxSets, Containers::ArrayView> poolSizes, Flags flags = {}); + /** @overload */ + explicit DescriptorPoolCreateInfo(UnsignedInt maxSets, std::initializer_list> poolSizes, Flags flags = {}); + + /** + * @brief Construct without initializing the contents + * + * Note that not even the `sType` field is set --- the structure has to + * be fully initialized afterwards in order to be usable. + */ + explicit DescriptorPoolCreateInfo(NoInitT) noexcept; + + /** + * @brief Construct from existing data + * + * Copies the existing values verbatim, pointers are kept unchanged + * without taking over the ownership. Modifying the newly created + * instance will not modify the original data nor the pointed-to data. + */ + explicit DescriptorPoolCreateInfo(const VkDescriptorPoolCreateInfo& info); + + /** @brief Copying is not allowed */ + DescriptorPoolCreateInfo(const DescriptorPoolCreateInfo&) = delete; + + /** @brief Move constructor */ + DescriptorPoolCreateInfo(DescriptorPoolCreateInfo&& other) noexcept; + + ~DescriptorPoolCreateInfo(); + + /** @brief Copying is not allowed */ + DescriptorPoolCreateInfo& operator=(const DescriptorPoolCreateInfo&) = delete; + + /** @brief Move assignment */ + DescriptorPoolCreateInfo& operator=(DescriptorPoolCreateInfo&& other) noexcept; + + /** @brief Underlying @type_vk{DescriptorPoolCreateInfo} structure */ + VkDescriptorPoolCreateInfo& operator*() { return _info; } + /** @overload */ + const VkDescriptorPoolCreateInfo& operator*() const { return _info; } + /** @overload */ + VkDescriptorPoolCreateInfo* operator->() { return &_info; } + /** @overload */ + const VkDescriptorPoolCreateInfo* operator->() const { return &_info; } + /** @overload */ + operator const VkDescriptorPoolCreateInfo*() const { return &_info; } + + private: + VkDescriptorPoolCreateInfo _info; + Containers::ArrayTuple _data; +}; + +CORRADE_ENUMSET_OPERATORS(DescriptorPoolCreateInfo::Flags) + +}} + +/* Make the definition complete -- it doesn't make sense to have a CreateInfo + without the corresponding object anyway. */ +#include "Magnum/Vk/DescriptorPool.h" + +#endif diff --git a/src/Magnum/Vk/DescriptorSetLayout.h b/src/Magnum/Vk/DescriptorSetLayout.h index 6d42d54a9..d537e6e5a 100644 --- a/src/Magnum/Vk/DescriptorSetLayout.h +++ b/src/Magnum/Vk/DescriptorSetLayout.h @@ -89,7 +89,7 @@ specify additional flags per binding. All of them require a certain @section Vk-DescriptorSetLayout-usage Descriptor set layout usage A descriptor set layout is used in a @ref PipelineLayout creation and -subsequently for descriptor set allocation from a descriptor pool. See the +subsequently for descriptor set allocation from a @ref DescriptorPool. See the corresponding class documentation for more information. */ class MAGNUM_VK_EXPORT DescriptorSetLayout { diff --git a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h index a7cd9ec9b..7165e7a64 100644 --- a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h +++ b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h @@ -74,6 +74,11 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { * submission will use the most recently set descriptors for * the binding and the updates do not invalidate the command * buffer. + * + * Descriptor set layouts using this flag can be only allocated + * from a @ref DescriptorPool that has + * @ref DescriptorPoolCreateInfo::Flag::UpdateAfterBind set as + * well. * @requires_vk_feature @ref DeviceFeature::DescriptorBindingSampledImageUpdateAfterBind * if used on a @ref DescriptorType::CombinedImageSampler / * @relativeref{DescriptorType,SampledImage} @@ -114,6 +119,10 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { * This descriptor binding has a variable size that will be * specified when a descriptor set is allocated using this layout, * and the @p descriptorCount value is treated as an upper bound. + * + * Allowed only on the last binding number in the layout, not + * allowed on a @ref DescriptorType::UniformBufferDynamic or + * @ref DescriptorType::StorageBufferDynamic. * @requires_vk_feature @ref DeviceFeature::DescriptorBindingVariableDescriptorCount */ VariableDescriptorCount = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT @@ -135,7 +144,9 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { * @param descriptorType Descriptor type * @param descriptorCount Number of descriptors contained in the * binding. If the shader binding is not an array, use @cpp 1 @ce, - * zero is allowed as well. + * zero is allowed as well. For a @ref Flag::VariableDescriptorCount + * this is used as an upper bound and a concrete size is specified + * during descriptor set allocation. * @param stages Shader stages that access the binding. * Use @cpp ~Vk::ShaderStages{} @ce to specify that all stages * may access the binding. diff --git a/src/Magnum/Vk/DescriptorType.h b/src/Magnum/Vk/DescriptorType.h index 494fe641e..13f6f6c03 100644 --- a/src/Magnum/Vk/DescriptorType.h +++ b/src/Magnum/Vk/DescriptorType.h @@ -41,7 +41,7 @@ namespace Magnum { namespace Vk { @m_since_latest Wraps @type_vk_keyword{DescriptorType}. -@see @ref DescriptorSetLayoutBinding +@see @ref DescriptorSetLayoutBinding, @ref DescriptorPoolCreateInfo @m_enum_values_as_keywords */ enum class DescriptorType: Int { diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index 5c40346b3..8279445a6 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -27,6 +27,7 @@ corrade_add_test(VkBufferTest BufferTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkCommandBufferTest CommandBufferTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk) +corrade_add_test(VkDescriptorPoolTest DescriptorPoolTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkDescriptorSetLayoutTest DescriptorSetLayoutTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDescriptorTypeTest DescriptorTypeTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceTest DeviceTest.cpp LIBRARIES MagnumVk) @@ -131,6 +132,7 @@ set_target_properties( VkBufferTest VkCommandBufferTest VkCommandPoolTest + VkDescriptorPoolTest VkDescriptorSetLayoutTest VkDescriptorTypeTest VkDeviceTest @@ -196,6 +198,7 @@ if(BUILD_VK_TESTS) corrade_add_test(VkBufferVkTest BufferVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkCommandBufferVkTest CommandBufferVkTest.cpp LIBRARIES MagnumVulkanTester) corrade_add_test(VkCommandPoolVkTest CommandPoolVkTest.cpp LIBRARIES MagnumVulkanTester) + corrade_add_test(VkDescriptorPoolVkTest DescriptorPoolVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkDescriptorSetLayoutVkTest DescriptorSetLayoutVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkDeviceVkTest DeviceVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkDevicePropertiesVkTest DevicePropertiesVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) @@ -248,6 +251,7 @@ if(BUILD_VK_TESTS) VkBufferVkTest VkCommandBufferVkTest VkCommandPoolVkTest + VkDescriptorPoolVkTest VkDescriptorSetLayoutVkTest VkDeviceVkTest VkDevicePropertiesVkTest diff --git a/src/Magnum/Vk/Test/DescriptorPoolTest.cpp b/src/Magnum/Vk/Test/DescriptorPoolTest.cpp new file mode 100644 index 000000000..150cb2190 --- /dev/null +++ b/src/Magnum/Vk/Test/DescriptorPoolTest.cpp @@ -0,0 +1,183 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 +#include +#include +#include + +#include "Magnum/Vk/DescriptorPoolCreateInfo.h" +#include "Magnum/Vk/DescriptorType.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DescriptorPoolTest: TestSuite::Tester { + explicit DescriptorPoolTest(); + + void createInfoConstruct(); + void createInfoConstructNoSets(); + void createInfoConstructNoPools(); + void createInfoConstructEmptyPool(); + void createInfoConstructNoInit(); + void createInfoConstructFromVk(); + void createInfoConstructCopy(); + void createInfoConstructMove(); + + void constructNoCreate(); + void constructCopy(); +}; + +DescriptorPoolTest::DescriptorPoolTest() { + addTests({&DescriptorPoolTest::createInfoConstruct, + &DescriptorPoolTest::createInfoConstructNoSets, + &DescriptorPoolTest::createInfoConstructNoPools, + &DescriptorPoolTest::createInfoConstructEmptyPool, + &DescriptorPoolTest::createInfoConstructNoInit, + &DescriptorPoolTest::createInfoConstructFromVk, + &DescriptorPoolTest::createInfoConstructCopy, + &DescriptorPoolTest::createInfoConstructMove, + + &DescriptorPoolTest::constructNoCreate, + &DescriptorPoolTest::constructCopy}); +} + +void DescriptorPoolTest::createInfoConstruct() { + DescriptorPoolCreateInfo info{5, { + {DescriptorType::CombinedImageSampler, 7}, + {DescriptorType::UniformBuffer, 3} + }, DescriptorPoolCreateInfo::Flag::FreeDescriptorSet|DescriptorPoolCreateInfo::Flag::UpdateAfterBind}; + CORRADE_COMPARE(info->flags, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT|VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT); + CORRADE_COMPARE(info->maxSets, 5); + CORRADE_COMPARE(info->poolSizeCount, 2); + CORRADE_VERIFY(info->pPoolSizes); + CORRADE_COMPARE(info->pPoolSizes[0].type, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); + CORRADE_COMPARE(info->pPoolSizes[0].descriptorCount, 7); + CORRADE_COMPARE(info->pPoolSizes[1].type, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + CORRADE_COMPARE(info->pPoolSizes[1].descriptorCount, 3); +} + +void DescriptorPoolTest::createInfoConstructNoSets() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + DescriptorPoolCreateInfo{0, {}}; + CORRADE_COMPARE(out.str(), "Vk::DescriptorPoolCreateInfo: there has to be at least one set\n"); +} + +void DescriptorPoolTest::createInfoConstructNoPools() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + DescriptorPoolCreateInfo{5, {}}; + CORRADE_COMPARE(out.str(), "Vk::DescriptorPoolCreateInfo: there has to be at least one pool\n"); +} + +void DescriptorPoolTest::createInfoConstructEmptyPool() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + DescriptorPoolCreateInfo{5, { + {DescriptorType::InputAttachment, 2}, + {DescriptorType::UniformBuffer, 0}, + }}; + CORRADE_COMPARE(out.str(), "Vk::DescriptorPoolCreateInfo: pool 1 of Vk::DescriptorType::UniformBuffer has no descriptors\n"); +} + +void DescriptorPoolTest::createInfoConstructNoInit() { + DescriptorPoolCreateInfo info{NoInit}; + info->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + new(&info) DescriptorPoolCreateInfo{NoInit}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); + + CORRADE_VERIFY(std::is_nothrow_constructible::value); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +void DescriptorPoolTest::createInfoConstructFromVk() { + VkDescriptorPoolCreateInfo vkInfo; + vkInfo.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2; + + DescriptorPoolCreateInfo info{vkInfo}; + CORRADE_COMPARE(info->sType, VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2); +} + +void DescriptorPoolTest::createInfoConstructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +void DescriptorPoolTest::createInfoConstructMove() { + DescriptorPoolCreateInfo a{5, { + {DescriptorType::CombinedImageSampler, 7}, + {DescriptorType::UniformBuffer, 3} + }}; + CORRADE_COMPARE(a->poolSizeCount, 2); + CORRADE_VERIFY(a->pPoolSizes); + + DescriptorPoolCreateInfo b = std::move(a); + CORRADE_COMPARE(a->poolSizeCount, 0); + CORRADE_VERIFY(!a->pPoolSizes); + CORRADE_COMPARE(b->poolSizeCount, 2); + CORRADE_VERIFY(b->pPoolSizes); + CORRADE_COMPARE(b->pPoolSizes[1].type, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); + + DescriptorPoolCreateInfo c{VkDescriptorPoolCreateInfo{}}; + c = std::move(b); + CORRADE_COMPARE(b->poolSizeCount, 0); + CORRADE_VERIFY(!b->pPoolSizes); + CORRADE_COMPARE(c->poolSizeCount, 2); + CORRADE_VERIFY(c->pPoolSizes); + CORRADE_COMPARE(c->pPoolSizes[1].type, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); +} + +void DescriptorPoolTest::constructNoCreate() { + { + DescriptorPool pool{NoCreate}; + CORRADE_VERIFY(!pool.handle()); + } + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +void DescriptorPoolTest::constructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DescriptorPoolTest) diff --git a/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp b/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp new file mode 100644 index 000000000..66a58ba5b --- /dev/null +++ b/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp @@ -0,0 +1,103 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 "Magnum/Vk/DescriptorPoolCreateInfo.h" +#include "Magnum/Vk/DescriptorType.h" +#include "Magnum/Vk/Result.h" +#include "Magnum/Vk/VulkanTester.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DescriptorPoolVkTest: VulkanTester { + explicit DescriptorPoolVkTest(); + + void construct(); + void constructMove(); + + void wrap(); +}; + +DescriptorPoolVkTest::DescriptorPoolVkTest() { + addTests({&DescriptorPoolVkTest::construct, + &DescriptorPoolVkTest::constructMove, + + &DescriptorPoolVkTest::wrap}); +} + +void DescriptorPoolVkTest::construct() { + { + DescriptorPool pool{device(), DescriptorPoolCreateInfo{5, { + {DescriptorType::UniformBuffer, 2} + }}}; + CORRADE_VERIFY(pool.handle()); + CORRADE_COMPARE(pool.handleFlags(), HandleFlag::DestroyOnDestruction); + } + + /* Shouldn't crash or anything */ + CORRADE_VERIFY(true); +} + +void DescriptorPoolVkTest::constructMove() { + DescriptorPool a{device(), DescriptorPoolCreateInfo{5, { + {DescriptorType::UniformBuffer, 2} + }}}; + VkDescriptorPool handle = a.handle(); + + DescriptorPool b = std::move(a); + CORRADE_VERIFY(!a.handle()); + CORRADE_COMPARE(b.handle(), handle); + CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction); + + DescriptorPool c{NoCreate}; + c = std::move(b); + CORRADE_VERIFY(!b.handle()); + CORRADE_COMPARE(b.handleFlags(), HandleFlags{}); + CORRADE_COMPARE(c.handle(), handle); + CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction); + + CORRADE_VERIFY(std::is_nothrow_move_constructible::value); + CORRADE_VERIFY(std::is_nothrow_move_assignable::value); +} + +void DescriptorPoolVkTest::wrap() { + VkDescriptorPool pool{}; + CORRADE_COMPARE(Result(device()->CreateDescriptorPool(device(), + DescriptorPoolCreateInfo{5, { + {DescriptorType::UniformBuffer, 2} + }}, + nullptr, &pool)), Result::Success); + + auto wrapped = DescriptorPool::wrap(device(), pool, HandleFlag::DestroyOnDestruction); + CORRADE_COMPARE(wrapped.handle(), pool); + + /* Release the handle again, destroy by hand */ + CORRADE_COMPARE(wrapped.release(), pool); + CORRADE_VERIFY(!wrapped.handle()); + device()->DestroyDescriptorPool(device(), pool, nullptr); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DescriptorPoolVkTest) diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 33b453d64..723772562 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -57,6 +57,8 @@ class CopyImageToBufferInfo; /* Not forward-declaring CopyBufferToImageInfo1D etc right now, I see no need */ enum class DependencyFlag: UnsignedInt; typedef Containers::EnumSet DependencyFlags; +class DescriptorPool; +class DescriptorPoolCreateInfo; class DescriptorSetLayout; class DescriptorSetLayoutCreateInfo; enum class DescriptorType: Int; From 1abb67a11926450cb01fa29d04455f57641989e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 14 Mar 2021 20:26:46 +0100 Subject: [PATCH 093/161] Vk: allow multiple values in MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(). Breaking this macro yet again, sorry -- now the result values are specified last and there can be any number of them, however they need to be all prefixed, as adding the prefix implicitly with the macro would be too much of a pain to implement, especially given the poor preprocessor capabilities of MSVC. --- doc/snippets/MagnumVk.cpp | 5 ++-- src/Magnum/Vk/Assert.h | 32 +++++++++++++---------- src/Magnum/Vk/DeviceProperties.cpp | 2 +- src/Magnum/Vk/Fence.cpp | 4 +-- src/Magnum/Vk/Test/AssertDisabledTest.cpp | 8 +++--- src/Magnum/Vk/Test/AssertTest.cpp | 14 +++++----- 6 files changed, 36 insertions(+), 29 deletions(-) diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index a3c8c966e..72a47e49c 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -195,8 +195,9 @@ Vk::Device device{instance, std::move(info)}; Vk::Device device{NoCreate}; VkFence fence{}; /* [MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR] */ -const Vk::Result result = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(NotReady, - vkGetFenceStatus(device, fence)); +const Vk::Result result = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR( + vkGetFenceStatus(device, fence), + Vk::Result::NotReady); if(result == Vk::Result::Success) { // signaled } else { diff --git a/src/Magnum/Vk/Assert.h b/src/Magnum/Vk/Assert.h index 60b860095..ca8305779 100644 --- a/src/Magnum/Vk/Assert.h +++ b/src/Magnum/Vk/Assert.h @@ -82,14 +82,14 @@ You can override this implementation by placing your own #endif /** -@brief Assert that a Vulkan function call succeeds or returns the specified result +@brief Assert that a Vulkan function call succeeds or returns any of the specified results @m_since_latest A variant of @ref MAGNUM_VK_INTERNAL_ASSERT_SUCCESS() that allows the call to -return specified @p result in addition to -@ref Magnum::Vk::Result::Success "Vk::Result::Success". The value specified in -@p result is directly the (unscoped) enum value and the macro returns the -actual result value. Example usage: +return any of the specified results in addition to +@ref Magnum::Vk::Result::Success "Result::Success". The variadic argument +accepts any number of @ref Magnum::Vk::Result "Result" values, the macro then +returns the actual result value. Example usage: @snippet MagnumVk.cpp MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR @@ -103,26 +103,30 @@ including the @ref Magnum/Vk/Assert.h header. #if defined(CORRADE_NO_ASSERT) || (defined(CORRADE_STANDARD_ASSERT) && defined(NDEBUG)) /* Defining it to just Magnum::Vk::Result(call) causes ugly warnings with asserts disabled, so it has to be a lambda even here :( */ -#define MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(result, call) \ +#define MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(call, ...) \ [&]() { \ return Magnum::Vk::Result(call); \ }() #elif defined(CORRADE_STANDARD_ASSERT) -#define MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(result, call) \ +#define MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(call, ...) \ [&]() { \ const Magnum::Vk::Result _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) = Magnum::Vk::Result(call); \ - assert(_CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) == Magnum::Vk::Result::Success || _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) == Magnum::Vk::Result::result); \ - return _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__); \ + for(const Magnum::Vk::Result _CORRADE_HELPER_PASTE(magnumVkResultCandidate, __LINE__): {Magnum::Vk::Result::Success, __VA_ARGS__}) { \ + if(_CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) == _CORRADE_HELPER_PASTE(magnumVkResultCandidate, __LINE__)) \ + return _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__); \ + } \ + assert(false); \ }() #else -#define MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(result, call) \ +#define MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(call, ...) \ [&]() { \ const Magnum::Vk::Result _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) = Magnum::Vk::Result(call); \ - if(_CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) != Magnum::Vk::Result::Success && _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) != Magnum::Vk::Result::result) { \ - Corrade::Utility::Error{Corrade::Utility::Error::defaultOutput()} << "Call " #call " failed with" << _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) << "at " __FILE__ ":" CORRADE_LINE_STRING; \ - std::abort(); \ + for(const Magnum::Vk::Result _CORRADE_HELPER_PASTE(magnumVkResultCandidate, __LINE__): {Magnum::Vk::Result::Success, __VA_ARGS__}) { \ + if(_CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) == _CORRADE_HELPER_PASTE(magnumVkResultCandidate, __LINE__)) \ + return _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__); \ } \ - return _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__); \ + Corrade::Utility::Error{Corrade::Utility::Error::defaultOutput()} << "Call " #call " failed with" << _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) << "at " __FILE__ ":" CORRADE_LINE_STRING; \ + std::abort(); \ }() #endif #endif diff --git a/src/Magnum/Vk/DeviceProperties.cpp b/src/Magnum/Vk/DeviceProperties.cpp index 739c5a8f7..f3c2d3786 100644 --- a/src/Magnum/Vk/DeviceProperties.cpp +++ b/src/Magnum/Vk/DeviceProperties.cpp @@ -562,7 +562,7 @@ UnsignedInt enumerateDevicesInto(Instance& instance, Containers::ArrayView handles{reinterpret_cast(out.data()), out.size()}; UnsignedInt count = out.size(); - MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Incomplete, instance->EnumeratePhysicalDevices(instance, &count, handles.data())); + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(instance->EnumeratePhysicalDevices(instance, &count, handles.data()), Result::Incomplete); /* Expect the final count isn't larger than the output array */ CORRADE_INTERNAL_ASSERT(count <= out.size()); diff --git a/src/Magnum/Vk/Fence.cpp b/src/Magnum/Vk/Fence.cpp index 01d4defb6..6c6818699 100644 --- a/src/Magnum/Vk/Fence.cpp +++ b/src/Magnum/Vk/Fence.cpp @@ -78,7 +78,7 @@ Fence& Fence::operator=(Fence&& other) noexcept { } bool Fence::status() { - return MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(NotReady, (**_device).GetFenceStatus(*_device, _handle)) == Result::Success; + return MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR((**_device).GetFenceStatus(*_device, _handle), Result::NotReady) == Result::Success; } void Fence::reset() { @@ -86,7 +86,7 @@ void Fence::reset() { } bool Fence::wait(const std::chrono::nanoseconds timeout) { - return MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Timeout, (**_device).WaitForFences(*_device, 1, &_handle, true, timeout.count())) == Result::Success; + return MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR((**_device).WaitForFences(*_device, 1, &_handle, true, timeout.count()), Result::Timeout) == Result::Success; } void Fence::wait() { diff --git a/src/Magnum/Vk/Test/AssertDisabledTest.cpp b/src/Magnum/Vk/Test/AssertDisabledTest.cpp index 82f73906b..0221fd51e 100644 --- a/src/Magnum/Vk/Test/AssertDisabledTest.cpp +++ b/src/Magnum/Vk/Test/AssertDisabledTest.cpp @@ -75,7 +75,7 @@ void AssertDisabledTest::successOr() { Result a = Result::ErrorUnknown; Result r = Result::ErrorExtensionNotPresent; - Result a2 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Incomplete, a = r); + Result a2 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(a = r, Result::Incomplete); CORRADE_COMPARE(a, Result::ErrorExtensionNotPresent); CORRADE_COMPARE(a2, a); @@ -83,7 +83,7 @@ void AssertDisabledTest::successOr() { /* Test also that a standalone macro won't cause warnings about unused expression results */ - MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(ErrorDeviceLost, Result::ErrorDeviceLost); + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Result::ErrorDeviceLost, Result::ErrorDeviceLost); } void AssertDisabledTest::vkSuccess() { @@ -104,7 +104,7 @@ void AssertDisabledTest::vkSuccessOr() { VkResult b = VK_ERROR_UNKNOWN; VkResult s = VK_ERROR_EXTENSION_NOT_PRESENT; - Result b2 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Incomplete, b = s); + Result b2 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(b = s, Result::Incomplete); CORRADE_COMPARE(Result(b), Result::ErrorExtensionNotPresent); CORRADE_COMPARE(b2, Result(b)); @@ -112,7 +112,7 @@ void AssertDisabledTest::vkSuccessOr() { /* Test also that a standalone macro won't cause warnings about unused expression results */ - MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(ErrorDeviceLost, VK_ERROR_DEVICE_LOST); + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(VK_ERROR_DEVICE_LOST, Result::ErrorDeviceLost); } }}}} diff --git a/src/Magnum/Vk/Test/AssertTest.cpp b/src/Magnum/Vk/Test/AssertTest.cpp index 1cf5c05a9..c4dae782f 100644 --- a/src/Magnum/Vk/Test/AssertTest.cpp +++ b/src/Magnum/Vk/Test/AssertTest.cpp @@ -81,18 +81,19 @@ void AssertTest::success() { void AssertTest::successOr() { Result a = Result::ErrorUnknown; - Result a2 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Incomplete, a = Result::Success); + Result a2 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(a = Result::Success, Result::Incomplete); CORRADE_COMPARE(a2, a); Result r = _failAssertSuccessOr ? Result::ErrorExtensionNotPresent : Result::Incomplete; - Result a3 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Incomplete, a = r); + /* Verify that multiple results work too and all get checked */ + Result a3 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(a = r, Result::ErrorOutOfDeviceMemory, Result::Incomplete); CORRADE_COMPARE(a, Result::Incomplete); CORRADE_COMPARE(a3, a); /* Test also that a standalone macro won't cause warnings about unused expression results */ - MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(ErrorDeviceLost, Result::ErrorDeviceLost); + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Result::ErrorDeviceLost, Result::ErrorDeviceLost); } void AssertTest::vkSuccess() { @@ -106,18 +107,19 @@ void AssertTest::vkSuccess() { void AssertTest::vkSuccessOr() { VkResult a = VK_ERROR_UNKNOWN; - Result a2 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Incomplete, a = VK_SUCCESS); + Result a2 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(a = VK_SUCCESS, Result::Incomplete); CORRADE_COMPARE(a2, Result(a)); VkResult s = _failAssertVkSuccessOr ? VK_ERROR_EXTENSION_NOT_PRESENT : VK_INCOMPLETE; - Result a3 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(Incomplete, a = s); + /* Verify that multiple results work too and all get checked */ + Result a3 = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(a = s, Result::ErrorOutOfDeviceMemory, Result::Incomplete); CORRADE_COMPARE(Result(a), Result::Incomplete); CORRADE_COMPARE(a3, Result(a)); /* Test also that a standalone macro won't cause warnings about unused expression results */ - MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(ErrorDeviceLost, VK_ERROR_DEVICE_LOST); + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(VK_ERROR_DEVICE_LOST, Result::ErrorDeviceLost); } }}}} From 0ef77cab3ab13eb434a72ae9bccfc61ea42451d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 15 Mar 2021 10:42:51 +0100 Subject: [PATCH 094/161] Vk: doc++ --- doc/vulkan-mapping.dox | 2 +- src/Magnum/Vk/CommandPool.h | 2 +- src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index 0a73aa051..358c22d0b 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -927,7 +927,7 @@ Vulkan enum | Matching API @type_vk{PipelineStageFlagBits}, \n @type_vk{PipelineStageFlags} | @ref PipelineStage, \n @ref PipelineStages @type_vk{PointClippingBehavior} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{PolygonMode} | | -@type_vk{PrimitveTopology} | @ref MeshPrimitive +@type_vk{PrimitiveTopology} | @ref MeshPrimitive @subsection vulkan-mapping-enums-q Q diff --git a/src/Magnum/Vk/CommandPool.h b/src/Magnum/Vk/CommandPool.h index 2be0ce34a..cf27bd20c 100644 --- a/src/Magnum/Vk/CommandPool.h +++ b/src/Magnum/Vk/CommandPool.h @@ -164,7 +164,7 @@ class MAGNUM_VK_EXPORT CommandPool { HandleFlags handleFlags() const { return _flags; } /** - * @brief Allocate a command buffer + * @brief Allocate a single command buffer * * @see @fn_vk_keyword{AllocateCommandBuffers} */ diff --git a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h index 7165e7a64..b072ca494 100644 --- a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h +++ b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h @@ -140,7 +140,7 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { /** * @brief Constructor * @param binding Binding corresponding to a particular - * binding in a shader + * binding in a shader. Has to be unique in the layout. * @param descriptorType Descriptor type * @param descriptorCount Number of descriptors contained in the * binding. If the shader binding is not an array, use @cpp 1 @ce, From ee560b42e974bacc275c2b1665e524299c03769a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 15 Mar 2021 14:51:18 +0100 Subject: [PATCH 095/161] Vk: suggest enabling the corresponding extension as well. --- doc/snippets/MagnumVk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index 72a47e49c..fb08bb3b5 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -365,6 +365,7 @@ Vk::Instance instance{NoCreate}; /* [DescriptorSetLayout-creation-binding-flags] */ Vk::Device device{instance, Vk::DeviceCreateInfo{DOXYGEN_IGNORE(Vk::pickDevice(instance))} DOXYGEN_IGNORE() + .addEnabledExtensions() .setEnabledFeatures( Vk::DeviceFeature::DescriptorBindingUniformBufferUpdateAfterBind| DOXYGEN_IGNORE(Vk::DeviceFeatures{}) From 412d54b25b4e151866459451e68f289809066543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 15 Mar 2021 17:14:56 +0100 Subject: [PATCH 096/161] Vk: implement descriptor set allocation, freeing and pool reset. --- doc/snippets/MagnumVk.cpp | 62 +++++ doc/vulkan-mapping.dox | 10 +- doc/vulkan-support.dox | 2 +- src/Magnum/Vk/CMakeLists.txt | 2 + src/Magnum/Vk/DescriptorPool.cpp | 92 ++++++- src/Magnum/Vk/DescriptorPool.h | 120 +++++++++ src/Magnum/Vk/DescriptorPoolCreateInfo.h | 9 +- src/Magnum/Vk/DescriptorSet.cpp | 69 ++++++ src/Magnum/Vk/DescriptorSet.h | 173 +++++++++++++ src/Magnum/Vk/DescriptorSetLayout.h | 11 +- src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h | 7 +- src/Magnum/Vk/Result.h | 7 +- src/Magnum/Vk/Test/CMakeLists.txt | 6 +- src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp | 228 ++++++++++++++++++ src/Magnum/Vk/Test/DescriptorSetTest.cpp | 62 +++++ src/Magnum/Vk/Test/DescriptorSetVkTest.cpp | 110 +++++++++ src/Magnum/Vk/Vk.h | 1 + 17 files changed, 950 insertions(+), 21 deletions(-) create mode 100644 src/Magnum/Vk/DescriptorSet.cpp create mode 100644 src/Magnum/Vk/DescriptorSet.h create mode 100644 src/Magnum/Vk/Test/DescriptorSetTest.cpp create mode 100644 src/Magnum/Vk/Test/DescriptorSetVkTest.cpp diff --git a/doc/snippets/MagnumVk.cpp b/doc/snippets/MagnumVk.cpp index fb08bb3b5..8978ae08d 100644 --- a/doc/snippets/MagnumVk.cpp +++ b/doc/snippets/MagnumVk.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -40,6 +41,7 @@ #include "Magnum/Vk/CommandPoolCreateInfo.h" #include "Magnum/Vk/ComputePipelineCreateInfo.h" #include "Magnum/Vk/DescriptorPoolCreateInfo.h" +#include "Magnum/Vk/DescriptorSet.h" #include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" #include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/DeviceCreateInfo.h" @@ -331,6 +333,66 @@ Vk::DescriptorPool pool{device, Vk::DescriptorPoolCreateInfo{8, { /* [DescriptorPool-creation] */ } +{ +/* [DescriptorSet-allocation] */ +Vk::DescriptorSetLayout layout{DOXYGEN_IGNORE(NoCreate)}; +Vk::DescriptorPool pool{DOXYGEN_IGNORE(NoCreate)}; + +Vk::DescriptorSet set = pool.allocate(layout); +/* [DescriptorSet-allocation] */ +} + +{ +Vk::DescriptorSetLayout layout{NoCreate}; +Vk::DescriptorPool pool{NoCreate}, overflowPool{NoCreate}; +/* [DescriptorSet-allocation-try] */ +Containers::Optional set = pool.tryAllocate(layout); + +/* Oops, the pool is full (or fragmented). Hope the plan B doesn't fail too. */ +if(!set) set = overflowPool.allocate(layout); +/* [DescriptorSet-allocation-try] */ +} + +{ +Vk::Device device{NoCreate}; +Vk::DescriptorSetLayout layout{NoCreate}; +/* [DescriptorSet-allocation-free] */ +Vk::DescriptorPool pool{device, Vk::DescriptorPoolCreateInfo{DOXYGEN_IGNORE(0), { + DOXYGEN_IGNORE() +}, Vk::DescriptorPoolCreateInfo::Flag::FreeDescriptorSet}}; + +{ + Vk::DescriptorSet set = pool.allocate(layout); + + // the set gets automatically freed at the end of scope +} +/* [DescriptorSet-allocation-free] */ +} + +{ +Vk::Instance instance{NoCreate}; +Vk::DescriptorPool pool{NoCreate}; +/* [DescriptorSet-allocation-variable] */ +Vk::Device device{instance, Vk::DeviceCreateInfo{DOXYGEN_IGNORE(Vk::pickDevice(instance))} + DOXYGEN_IGNORE() + .addEnabledExtensions() + .setEnabledFeatures( + Vk::DeviceFeature::DescriptorBindingVariableDescriptorCount| + DOXYGEN_IGNORE(Vk::DeviceFeatures{}) + ) +}; + +Vk::DescriptorSetLayout layout{device, Vk::DescriptorSetLayoutCreateInfo{ + {{DOXYGEN_IGNORE(0), Vk::DescriptorType::SampledImage, 8, + Vk::ShaderStage::Fragment, + Vk::DescriptorSetLayoutBinding::Flag::VariableDescriptorCount}}, + DOXYGEN_IGNORE() +}}; + +Vk::DescriptorSet set = pool.allocate(layout, 4); +/* [DescriptorSet-allocation-variable] */ +} + { Vk::Device device{NoCreate}; /* The include should be a no-op here since it was already included above */ diff --git a/doc/vulkan-mapping.dox b/doc/vulkan-mapping.dox index 358c22d0b..617d805c0 100644 --- a/doc/vulkan-mapping.dox +++ b/doc/vulkan-mapping.dox @@ -59,7 +59,7 @@ Vulkan handle | Matching API @type_vk{DebugReportCallbackEXT} @m_class{m-label m-danger} **deprecated** @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DebugUtilsMessengerEXT} @m_class{m-label m-flat m-warning} **EXT** | | @type_vk{DescriptorPool} | @ref DescriptorPool -@type_vk{DescriptorSet} | | +@type_vk{DescriptorSet} | @ref DescriptorSet @type_vk{DescriptorSetLayout} | @ref DescriptorSetLayout @type_vk{DescriptorUpdateTemplate} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{Device} | @ref Device @@ -91,7 +91,7 @@ Vulkan handle | Matching API Vulkan function | Matching API --------------------------------------- | ------------ @fn_vk{AllocateCommandBuffers}, \n @fn_vk{FreeCommandBuffers} | @ref CommandPool::allocate(), @ref CommandBuffer destructor -@fn_vk{AllocateDescriptorSets}, \n @fn_vk{FreeDescriptorSets} | | +@fn_vk{AllocateDescriptorSets}, \n @fn_vk{FreeDescriptorSets} | @ref DescriptorPool::allocate(), @ref DescriptorSet destructor @fn_vk{AllocateMemory}, \n @fn_vk{FreeMemory} | @ref Memory constructor and destructor @subsection vulkan-mapping-functions-b B @@ -325,7 +325,7 @@ Vulkan function | Matching API --------------------------------------- | ------------ @fn_vk{ResetCommandBuffer} | @ref CommandBuffer::reset() @fn_vk{ResetCommandPool} | @ref CommandPool::reset() -@fn_vk{ResetDescriptorPool} | | +@fn_vk{ResetDescriptorPool} | @ref DescriptorPool::reset() @fn_vk{ResetFences} | @ref Fence::reset() @fn_vk{ResetQueryPool} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @@ -465,12 +465,12 @@ Vulkan structure | Matching API @type_vk{DescriptorImageInfo} | | @type_vk{DescriptorPoolCreateInfo} | @ref DescriptorPoolCreateInfo @type_vk{DescriptorPoolSize} | @ref DescriptorPoolCreateInfo -@type_vk{DescriptorSetAllocateInfo} | | +@type_vk{DescriptorSetAllocateInfo} | not exposed, internal to @ref DescriptorPool::allocate(VkDescriptorSetLayout) @type_vk{DescriptorSetLayoutBinding} | @ref DescriptorSetLayoutBinding @type_vk{DescriptorSetLayoutBindingFlagsCreateInfo} @m_class{m-label m-flqat m-success} **EXT, 1.2** | @ref DescriptorSetLayoutCreateInfo @type_vk{DescriptorSetLayoutCreateInfo} | @ref DescriptorSetLayoutCreateInfo @type_vk{DescriptorSetLayoutSupport} @m_class{m-label m-flat m-success} **KHR, 1.1** | | -@type_vk{DescriptorSetVariableDescriptorCountAllocateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | | +@type_vk{DescriptorSetVariableDescriptorCountAllocateInfo} @m_class{m-label m-flat m-success} **EXT, 1.2** | not exposed, internal to @ref DescriptorPool::allocate(VkDescriptorSetLayout, UnsignedInt) @type_vk{DescriptorSetVariableDescriptorCountLayoutSupport} @m_class{m-label m-flat m-success} **EXT, 1.2** | | @type_vk{DescriptorUpdateTemplateEntry} @m_class{m-label m-flat m-success} **KHR, 1.1** | | @type_vk{DescriptorUpdateTemplateCreateInfo} @m_class{m-label m-flat m-success} **KHR, 1.1** | | diff --git a/doc/vulkan-support.dox b/doc/vulkan-support.dox index ce90aeae7..2666bb064 100644 --- a/doc/vulkan-support.dox +++ b/doc/vulkan-support.dox @@ -90,7 +90,7 @@ Extension | Status @vk_extension{KHR,create_renderpass2} | done @vk_extension{EXT,sampler_filter_minmax} | | @vk_extension{KHR,image_format_list} | | -@vk_extension{EXT,descriptor_indexing} | done except properties and variable descriptor count allocation +@vk_extension{EXT,descriptor_indexing} | done except properties @vk_extension{EXT,shader_viewport_index_layer} | | @vk_extension{KHR,draw_indirect_count} | | @vk_extension{KHR,shader_subgroup_extended_types} | | diff --git a/src/Magnum/Vk/CMakeLists.txt b/src/Magnum/Vk/CMakeLists.txt index f4d189ccb..a12bbca0d 100644 --- a/src/Magnum/Vk/CMakeLists.txt +++ b/src/Magnum/Vk/CMakeLists.txt @@ -29,6 +29,7 @@ find_package(Vulkan REQUIRED) set(MagnumVk_SRCS CommandBuffer.cpp CommandPool.cpp + DescriptorSet.cpp DescriptorSetLayout.cpp DescriptorType.cpp Extensions.cpp @@ -77,6 +78,7 @@ set(MagnumVk_HEADERS ComputePipelineCreateInfo.h DescriptorPool.h DescriptorPoolCreateInfo.h + DescriptorSet.h DescriptorSetLayout.h DescriptorSetLayoutCreateInfo.h DescriptorType.h diff --git a/src/Magnum/Vk/DescriptorPool.cpp b/src/Magnum/Vk/DescriptorPool.cpp index d9a1616c1..2feeb1f75 100644 --- a/src/Magnum/Vk/DescriptorPool.cpp +++ b/src/Magnum/Vk/DescriptorPool.cpp @@ -27,8 +27,10 @@ #include "DescriptorPoolCreateInfo.h" #include +#include #include "Magnum/Vk/Assert.h" +#include "Magnum/Vk/DescriptorSet.h" #include "Magnum/Vk/DescriptorType.h" #include "Magnum/Vk/Device.h" #include "Magnum/Vk/Result.h" @@ -99,13 +101,13 @@ DescriptorPool DescriptorPool::wrap(Device& device, const VkDescriptorPool handl return out; } -DescriptorPool::DescriptorPool(Device& device, const DescriptorPoolCreateInfo& info): _device{&device}, _flags{HandleFlag::DestroyOnDestruction} { +DescriptorPool::DescriptorPool(Device& device, const DescriptorPoolCreateInfo& info): _device{&device}, _flags{HandleFlag::DestroyOnDestruction}, _freeAllocatedSets{!!(info->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)} { MAGNUM_VK_INTERNAL_ASSERT_SUCCESS(device->CreateDescriptorPool(device, info, nullptr, &_handle)); } DescriptorPool::DescriptorPool(NoCreateT): _device{}, _handle{} {} -DescriptorPool::DescriptorPool(DescriptorPool&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags} { +DescriptorPool::DescriptorPool(DescriptorPool&& other) noexcept: _device{other._device}, _handle{other._handle}, _flags{other._flags}, _freeAllocatedSets{other._freeAllocatedSets} { other._handle = {}; } @@ -119,9 +121,95 @@ DescriptorPool& DescriptorPool::operator=(DescriptorPool&& other) noexcept { swap(other._device, _device); swap(other._handle, _handle); swap(other._flags, _flags); + swap(other._freeAllocatedSets, _freeAllocatedSets); return *this; } +std::pair DescriptorPool::allocateInternal(const VkDescriptorSetLayout layout) { + DescriptorSet set{NoCreate}; + set._device = _device; + set._pool = _handle; + set._flags = _freeAllocatedSets ? HandleFlag::DestroyOnDestruction : HandleFlags{}; + + VkDescriptorSetAllocateInfo info{}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + info.descriptorPool = _handle; + info.descriptorSetCount = 1; + info.pSetLayouts = &layout; + /* VK_ERROR_OUT_OF_POOL_MEMORY is only available since VK_KHR_maintenance1 + and it's not really clear what was supposed to happen before that. At + the very least, running the allocateFail() test using + + ./VkDescriptorPoolVkTest --magnum-vulkan-version 1.0 --magnum-enable-layers VK_LAYER_KHRONOS_validation + + without VK_KHR_maintenance1 enabled, the validation layer complains that + I'm allocating from a pool that doesn't have enough free items, which + implies it used to be a user error and thus the driver is free to do + *anything*, including random crashes, as noted on + https://community.khronos.org/t/descriptor-pool-able-to-allocate-even-though-pool-should-be-empty/7330/6 + + From practical testing, even the oldest Vulkan driver I have (ARM Mali + on Huawei P9, Vulkan 1.0.66) seems to return VK_ERROR_OUT_OF_POOL_MEMORY + no matter whether the extension is enabled or not. So I'll assume all + contemporary drivers in early 2021 do this, there's nothing I can do + otherwise. */ + const Result result = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR((**_device).AllocateDescriptorSets(*_device, &info, &set._handle), Result::ErrorOutOfPoolMemory, Result::ErrorFragmentedPool); + return {result, std::move(set)}; +} + +DescriptorSet DescriptorPool::allocate(const VkDescriptorSetLayout layout) { + std::pair out = allocateInternal(layout); + CORRADE_ASSERT(out.first == Result::Success, + "Vk::DescriptorPool::allocate(): allocation failed with" << out.first, std::move(out.second)); + return std::move(out.second); +} + +Containers::Optional DescriptorPool::tryAllocate(const VkDescriptorSetLayout layout) { + std::pair out = allocateInternal(layout); + if(out.first != Result::Success) return {}; + return std::move(out.second); +} + +std::pair DescriptorPool::allocateInternal(const VkDescriptorSetLayout layout, const UnsignedInt variableDescriptorCount) { + DescriptorSet set{NoCreate}; + set._device = _device; + set._pool = _handle; + set._flags = _freeAllocatedSets ? HandleFlag::DestroyOnDestruction : HandleFlags{}; + + VkDescriptorSetVariableDescriptorCountAllocateInfo variableInfo{}; + variableInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO; + variableInfo.descriptorSetCount = 1; + variableInfo.pDescriptorCounts = &variableDescriptorCount; + + VkDescriptorSetAllocateInfo info{}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + info.pNext = &variableInfo; + info.descriptorPool = _handle; + info.descriptorSetCount = 1; + info.pSetLayouts = &layout; + /* See the not about VK_ERROR_OUT_OF_POOL_MEMORY and VK_KHR_maintenance1 + in the other allocateInternal() implementation above. */ + const Result result = MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR((**_device).AllocateDescriptorSets(*_device, &info, &set._handle), Result::ErrorOutOfPoolMemory, Result::ErrorFragmentedPool); + return {result, std::move(set)}; +} + +DescriptorSet DescriptorPool::allocate(const VkDescriptorSetLayout layout, const UnsignedInt variableDescriptorCount) { + std::pair out = allocateInternal(layout, variableDescriptorCount); + CORRADE_ASSERT(out.first == Result::Success, + "Vk::DescriptorPool::allocate(): allocation failed with" << out.first, std::move(out.second)); + return std::move(out.second); +} + +Containers::Optional DescriptorPool::tryAllocate(const VkDescriptorSetLayout layout, const UnsignedInt variableDescriptorCount) { + std::pair out = allocateInternal(layout, variableDescriptorCount); + if(out.first != Result::Success) return {}; + return std::move(out.second); +} + +void DescriptorPool::reset() { + MAGNUM_VK_INTERNAL_ASSERT_SUCCESS((**_device).ResetDescriptorPool(*_device, _handle, 0)); +} + VkDescriptorPool DescriptorPool::release() { const VkDescriptorPool handle = _handle; _handle = {}; diff --git a/src/Magnum/Vk/DescriptorPool.h b/src/Magnum/Vk/DescriptorPool.h index 7976b435e..c610ea8d4 100644 --- a/src/Magnum/Vk/DescriptorPool.h +++ b/src/Magnum/Vk/DescriptorPool.h @@ -30,6 +30,8 @@ * @m_since_latest */ +#include + #include "Magnum/Tags.h" #include "Magnum/Vk/Handle.h" #include "Magnum/Vk/visibility.h" @@ -54,6 +56,9 @@ following snippet creates a pool allowing to allocate at most 8 descriptor sets with 24 sampler bindings and 16 uniform bindings: @snippet MagnumVk.cpp DescriptorPool-creation + +With a descriptor pool created, you can allocate descriptor sets from it. See +the @ref DescriptorSet class for details. */ class MAGNUM_VK_EXPORT DescriptorPool { public: @@ -68,6 +73,17 @@ class MAGNUM_VK_EXPORT DescriptorPool { * a descriptor pool created using a constructor, the Vulkan descriptor * pool is by default not deleted on destruction, use @p flags for * different behavior. + * + * @m_class{m-note m-warning} + * + * @par + * Note that descriptor sets allocated using a pool wrapped by + * this function have no way to know if the pool was created with + * @ref DescriptorPoolCreateInfo::Flag::FreeDescriptorSet and thus + * won't be freeing themselves on destruction. If you need such + * behavior on these, re-wrap the allocated sets with appropriate + * @ref HandleFlags again using @ref DescriptorSet::wrap(). + * * @see @ref release() */ static DescriptorPool wrap(Device& device, VkDescriptorPool handle, HandleFlags flags = {}); @@ -120,6 +136,106 @@ class MAGNUM_VK_EXPORT DescriptorPool { /** @brief Handle flags */ HandleFlags handleFlags() const { return _flags; } + /** + * @brief Allocate a single descriptor set + * + * If @p layout contains a binding with + * @ref DescriptorSetLayoutBinding::Flag::VariableDescriptorCount set, + * the allocated descriptor count will be @cpp 0 @ce. Use + * @ref allocate(VkDescriptorSetLayout, UnsignedInt) in that case + * instead. + * + * If allocation fails due to exhaustion of pool memory or due to + * fragmentation, the function aborts with an error message. For + * graceful handling of such failures use + * @ref tryAllocate(VkDescriptorSetLayout) instead. + * @see @ref reset(), @fn_vk_keyword{AllocateDescriptorSets} + */ + DescriptorSet allocate(VkDescriptorSetLayout layout); + + /** + * @brief Try to allocate a single descriptor set + * + * Compared to @ref allocate(VkDescriptorSetLayout), if the allocation + * fails with @ref Result::ErrorOutOfPoolMemory or + * @ref Result::ErrorFragmentedPool, @ref Containers::NullOpt is + * returned instead of aborting to allow the application to recover and + * choose a different strategy. + * + * If Vulkan 1.1 is not supported by the device and the + * @vk_extension{KHR,maintenance1} extension isn't enabled on the + * device, allocation failures are treated as user error the driver is + * free to do basically anything. Fortunately most implementations + * support this extension nowadays and so it should be safe to assume + * @ref Result::ErrorOutOfPoolMemory gets properly returned in case of + * a failure. + */ + Containers::Optional tryAllocate(VkDescriptorSetLayout layout); + + /** + * @brief Allocate a single descriptor set with a variable descriptor count + * + * Compared to @ref allocate(VkDescriptorSetLayout), the + * @p variableDescriptorCount is used for a binding that was created + * with @ref DescriptorSetLayoutBinding::Flag::VariableDescriptorCount + * and is expected to not be larger than the the count specified in the + * layout. + * + * If allocation fails due to exhaustion of pool memory or due to + * fragmentation, the function aborts with an error message. For + * graceful handling of such failures use + * @ref tryAllocate(VkDescriptorSetLayout, UnsignedInt) instead. + * @see @type_vk_keyword{DescriptorSetVariableDescriptorCountAllocateInfo} + * @requires_vk_feature @ref DeviceFeature::DescriptorBindingVariableDescriptorCount + */ + DescriptorSet allocate(VkDescriptorSetLayout layout, UnsignedInt variableDescriptorCount); + + /** + * @brief Try to allocate a single descriptor set with a variable descriptor count + * + * Compared to @ref allocate(VkDescriptorSetLayout, UnsignedInt), if + * the allocation fails with @ref Result::ErrorOutOfPoolMemory or + * @ref Result::ErrorFragmentedPool, @ref Containers::NullOpt is + * returned instead of aborting to allow the application to recover and + * choose a different strategy. + * + * If Vulkan 1.1 is not supported by the device and the + * @vk_extension{KHR,maintenance1} extension isn't enabled on the + * device, allocation failures are treated as user error the driver is + * free to do basically anything. Fortunately most implementations + * support this extension nowadays and so it should be safe to assume + * @ref Result::ErrorOutOfPoolMemory gets properly returned in case of + * a failure. + */ + Containers::Optional tryAllocate(VkDescriptorSetLayout layout, UnsignedInt variableDescriptorCount); + + /** + * @brief Reset the pool + * + * Frees all descriptor sets allocated from this pool, making it empty + * again. + * + * @m_class{m-block m-warning} + * + * @par DescriptorSet destruction order + * All @ref DescriptorSet instances returned from @ref allocate() + * / @ref tryAllocate() become invalid after calling this + * function. While by default the @ref DescriptorSet does nothing + * and such behavior is fine, for a pool with + * @ref DescriptorPoolCreateInfo::Flag::FreeDescriptorSet + * enabled this would mean @fn_vk{FreeDescriptorSets} gets called + * with invalid descriptor set handles. To prevent that from + * happening either ensure all @ref DescriptorSet instances are + * gone by the time you call @ref reset(), or explicitly call + * @ref DescriptorSet::release() on each to make them empty + * without freeing anything. + * + * @see @ref allocate(), + * @ref DescriptorPoolCreateInfo::Flag::FreeDescriptorSet, + * @fn_vk{ResetDescriptorPool} + */ + void reset(); + /** * @brief Release the underlying Vulkan descriptor pool * @@ -132,11 +248,15 @@ class MAGNUM_VK_EXPORT DescriptorPool { VkDescriptorPool release(); private: + MAGNUM_VK_LOCAL std::pair allocateInternal(VkDescriptorSetLayout layout); + MAGNUM_VK_LOCAL std::pair allocateInternal(VkDescriptorSetLayout layout, UnsignedInt variableDescriptorCount); + /* Can't be a reference because of the NoCreate constructor */ Device* _device; VkDescriptorPool _handle; HandleFlags _flags; + bool _freeAllocatedSets; }; }} diff --git a/src/Magnum/Vk/DescriptorPoolCreateInfo.h b/src/Magnum/Vk/DescriptorPoolCreateInfo.h index 3d84c3934..c7dd0ca94 100644 --- a/src/Magnum/Vk/DescriptorPoolCreateInfo.h +++ b/src/Magnum/Vk/DescriptorPoolCreateInfo.h @@ -70,8 +70,13 @@ class MAGNUM_VK_EXPORT DescriptorPoolCreateInfo { * * @par * Not using this flag may help the driver to use simpler - * per-pool allocators instead of per-set. Without this flag - * set, descriptor pool fragmentation can't occur. + * per-pool allocators instead of per-set. With this flag set, + * descriptor pool fragmentation may occur, which can result + * in @ref DescriptorPool::allocate() failures even if the + * number of individual free descriptors in the pool is large + * enough. + * + * @see @ref Result::ErrorFragmentedPool */ FreeDescriptorSet = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, diff --git a/src/Magnum/Vk/DescriptorSet.cpp b/src/Magnum/Vk/DescriptorSet.cpp new file mode 100644 index 000000000..1af1c46ae --- /dev/null +++ b/src/Magnum/Vk/DescriptorSet.cpp @@ -0,0 +1,69 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 "DescriptorSet.h" + +#include "Magnum/Vk/Assert.h" +#include "Magnum/Vk/Device.h" +#include "Magnum/Vk/Result.h" + +namespace Magnum { namespace Vk { + +DescriptorSet DescriptorSet::wrap(Device& device, const VkDescriptorPool pool, const VkDescriptorSet handle, const HandleFlags flags) { + DescriptorSet out{NoCreate}; + out._device = &device; + out._pool = pool; + out._handle = handle; + out._flags = flags; + return out; +} + +DescriptorSet::DescriptorSet(NoCreateT): _device{}, _pool{}, _handle{} {} + +DescriptorSet::DescriptorSet(DescriptorSet&& other) noexcept: _device{other._device}, _pool{other._pool}, _handle{other._handle}, _flags{other._flags} { + other._handle = {}; +} + +DescriptorSet::~DescriptorSet() { + if(_handle && (_flags & HandleFlag::DestroyOnDestruction)) + (**_device).FreeDescriptorSets(*_device, _pool, 1, &_handle); +} + +DescriptorSet& DescriptorSet::operator=(DescriptorSet&& other) noexcept { + using std::swap; + swap(other._device, _device); + swap(other._pool, _pool); + swap(other._handle, _handle); + swap(other._flags, _flags); + return *this; +} + +VkDescriptorSet DescriptorSet::release() { + const VkDescriptorSet handle = _handle; + _handle = {}; + return handle; +} + +}} diff --git a/src/Magnum/Vk/DescriptorSet.h b/src/Magnum/Vk/DescriptorSet.h new file mode 100644 index 000000000..f684510b7 --- /dev/null +++ b/src/Magnum/Vk/DescriptorSet.h @@ -0,0 +1,173 @@ +#ifndef Magnum_Vk_DescriptorSet_h +#define Magnum_Vk_DescriptorSet_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Vk::DescriptorSet + * @m_since_latest + */ + +#include "Magnum/Tags.h" +#include "Magnum/Vk/Handle.h" +#include "Magnum/Vk/Vk.h" +#include "Magnum/Vk/Vulkan.h" +#include "Magnum/Vk/visibility.h" + +namespace Magnum { namespace Vk { + +/** +@brief Descriptor set +@m_since_latest + +Wraps a @type_vk_keyword{DescriptorSet}. A descriptor set is allocated from a +@ref DescriptorPool for a particular @ref DescriptorSetLayout and specifies +what descriptors (such as uniform buffers or samplers) are bound to shaders. + +@section Vk-DescriptorSet-allocation Descriptor set allocation + +Given a @ref DescriptorSetLayout and a compatible @ref DescriptorPool with +enough free slots, asingle descriptor set for given layout can be allocated +with @ref DescriptorPool::allocate(): + +@snippet MagnumVk.cpp DescriptorSet-allocation + +When allocating more than what the pool has, the @ref DescriptorPool::allocate() +function aborts with an error message. In cases where the application is very +dynamic and cannot predict that a pools is large enough, you can use +@ref DescriptorPool::tryAllocate() instead and handle the failure gracefully +--- for example by recycling unused sets or by allocating from a different +pool: + +@snippet MagnumVk.cpp DescriptorSet-allocation-try + +@subsection Vk-DescriptorSet-allocation-free Freeing descriptor sets + +By default, the @ref DescriptorSet destructor is a no-op and descriptor sets +are all freed together on a call to @ref DescriptorPool::reset(). At that point +all existing @ref DescriptorSet instances become invalid. Alternatively, the +pool can be created with @ref DescriptorPoolCreateInfo::Flag::FreeDescriptorSet, +which then makes a @ref DescriptorSet free itself on destruction, allowing more +descriptor sets to be allocated without resetting the whole pool. Using this +flag however can cause allocation to fail also due to pool fragmentation, not +just when exhausing all available resources: + +@snippet MagnumVk.cpp DescriptorSet-allocation-free + +@subsection Vk-DescriptorSet-allocation-variable Variable descriptor count allocation + +If the descriptor set layout contains a descriptor with variable count (there +has to be at most one and it has to be the last binding), a concrete count is +specified in the call to @ref DescriptorPool::allocate(VkDescriptorSetLayout, UnsignedInt). Here the fragment shader can access up to 8 sampled images and +we're allocating four: + +@snippet MagnumVk.cpp DescriptorSet-allocation-variable +*/ +class MAGNUM_VK_EXPORT DescriptorSet { + public: + /** + * @brief Wrap existing Vulkan handle + * @param device Vulkan device the descriptor pool is + * created on + * @param pool Vulkan descriptor pool the set is + * allocated from + * @param handle The @type_vk{DescriptorSet} handle + * @param flags Handle flags + * + * The @p handle is expected to be originating from @p device. The + * Vulkan descriptor set is by default not freed on destruction --- if + * the handle comes from a pool with + * @ref DescriptorPoolCreateInfo::Flag::FreeDescriptorSet set and you + * want it to be freed on destruction, pass + * @ref HandleFlag::DestroyOnDestruction to @p flags. + * @see @ref release() + */ + static DescriptorSet wrap(Device& device, VkDescriptorPool pool, VkDescriptorSet handle, HandleFlags flags = {}); + + /** + * @brief Construct without creating the fence + * + * The constructed instance is equivalent to moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + */ + explicit DescriptorSet(NoCreateT); + + /** @brief Copying is not allowed */ + DescriptorSet(const DescriptorSet&) = delete; + + /** @brief Move constructor */ + DescriptorSet(DescriptorSet&& other) noexcept; + + /** + * @brief Destructor + * + * Frees associated @type_vk{DescriptorSet} handle if it was allocated + * from a pool with @ref DescriptorPoolCreateInfo::Flag::FreeDescriptorSet + * set or if it was created using @ref wrap() with + * @ref HandleFlag::DestroyOnDestruction specified. Otherwise does + * nothing. + * @see @fn_vk_keyword{FreeDescriptorSets}, @ref release() + */ + ~DescriptorSet(); + + /** @brief Copying is not allowed */ + DescriptorSet& operator=(const DescriptorSet&) = delete; + + /** @brief Move assignment */ + DescriptorSet& operator=(DescriptorSet&& other) noexcept; + + /** @brief Underlying @type_vk{DescriptorSet} handle */ + VkDescriptorSet handle() { return _handle; } + /** @overload */ + operator VkDescriptorSet() { return _handle; } + + /** @brief Handle flags */ + HandleFlags handleFlags() const { return _flags; } + + /** + * @brief Release the underlying Vulkan descriptor set + * + * Releases ownership of the Vulkan descriptor set and returns its + * handle so @fn_vk{FreeDescriptorSets} is not called on destruction. + * The internal state is then equivalent to moved-from state. + * @see @ref wrap() + */ + VkDescriptorSet release(); + + private: + friend DescriptorPool; + + /* Can't be a reference because of the NoCreate constructor */ + Device* _device; + + VkDescriptorPool _pool; + VkDescriptorSet _handle; + HandleFlags _flags; +}; + +}} + +#endif diff --git a/src/Magnum/Vk/DescriptorSetLayout.h b/src/Magnum/Vk/DescriptorSetLayout.h index d537e6e5a..ced48ee43 100644 --- a/src/Magnum/Vk/DescriptorSetLayout.h +++ b/src/Magnum/Vk/DescriptorSetLayout.h @@ -42,9 +42,10 @@ namespace Magnum { namespace Vk { @brief Descriptor set layout @m_since_latest -Wraps a @type_vk_keyword{DescriptorSetLayout}. A descriptor set layout lists -descriptors (such as uniform buffers or samplers) used by shaders in a -@ref Pipeline. +Wraps a @type_vk_keyword{DescriptorSetLayout}. A descriptor set layout +specifies what descriptors (such as uniform buffers or samplers) can be used by +shaders in a @ref Pipeline, concrete descriptors are then bound using a +@ref DescriptorSet. @section Vk-DescriptorSetLayout-creation Descriptor set layout creation @@ -89,8 +90,8 @@ specify additional flags per binding. All of them require a certain @section Vk-DescriptorSetLayout-usage Descriptor set layout usage A descriptor set layout is used in a @ref PipelineLayout creation and -subsequently for descriptor set allocation from a @ref DescriptorPool. See the -corresponding class documentation for more information. +subsequently for @ref DescriptorSet allocation from a @ref DescriptorPool. See +the corresponding class documentation for more information. */ class MAGNUM_VK_EXPORT DescriptorSetLayout { public: diff --git a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h index b072ca494..8e6f5d998 100644 --- a/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h +++ b/src/Magnum/Vk/DescriptorSetLayoutCreateInfo.h @@ -117,8 +117,9 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { /** * This descriptor binding has a variable size that will be - * specified when a descriptor set is allocated using this layout, - * and the @p descriptorCount value is treated as an upper bound. + * specified in @ref DescriptorPool::allocate(VkDescriptorSetLayout, UnsignedInt), + * and the @p descriptorCount value specified in the constructor is + * treated as an upper bound. * * Allowed only on the last binding number in the layout, not * allowed on a @ref DescriptorType::UniformBufferDynamic or @@ -146,7 +147,7 @@ class MAGNUM_VK_EXPORT DescriptorSetLayoutBinding { * binding. If the shader binding is not an array, use @cpp 1 @ce, * zero is allowed as well. For a @ref Flag::VariableDescriptorCount * this is used as an upper bound and a concrete size is specified - * during descriptor set allocation. + * in @ref DescriptorPool::allocate(VkDescriptorSetLayout, UnsignedInt). * @param stages Shader stages that access the binding. * Use @cpp ~Vk::ShaderStages{} @ce to specify that all stages * may access the binding. diff --git a/src/Magnum/Vk/Result.h b/src/Magnum/Vk/Result.h index 66a012131..88a2e8bc9 100644 --- a/src/Magnum/Vk/Result.h +++ b/src/Magnum/Vk/Result.h @@ -139,7 +139,9 @@ enum class Result: Int { ErrorFormatNotSupported = VK_ERROR_FORMAT_NOT_SUPPORTED, /** - * A pool allocation has failed due to fragmentation of the pool's memory + * A pool allocation has failed due to fragmentation of the pool's memory. + * @see @ref DescriptorPool::allocate(), + * @ref DescriptorPoolCreateInfo::Flag::FreeDescriptorSet */ ErrorFragmentedPool = VK_ERROR_FRAGMENTED_POOL, @@ -152,7 +154,8 @@ enum class Result: Int { /** * A pool memory allocation has failed. * @see @ref Result::ErrorOutOfHostMemory, - * @ref Result::ErrorOutOfDeviceMemory + * @ref Result::ErrorOutOfDeviceMemory, + * @ref DescriptorPool::allocate() * @requires_vk11 Extension @vk_extension{KHR,maintenance1} */ ErrorOutOfPoolMemory = VK_ERROR_OUT_OF_POOL_MEMORY, diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index 8279445a6..fbe926370 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -28,6 +28,7 @@ corrade_add_test(VkBufferTest BufferTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkCommandBufferTest CommandBufferTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDescriptorPoolTest DescriptorPoolTest.cpp LIBRARIES MagnumVkTestLib) +corrade_add_test(VkDescriptorSetTest DescriptorSetTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDescriptorSetLayoutTest DescriptorSetLayoutTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDescriptorTypeTest DescriptorTypeTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkDeviceTest DeviceTest.cpp LIBRARIES MagnumVk) @@ -133,6 +134,7 @@ set_target_properties( VkCommandBufferTest VkCommandPoolTest VkDescriptorPoolTest + VkDescriptorSetTest VkDescriptorSetLayoutTest VkDescriptorTypeTest VkDeviceTest @@ -198,7 +200,8 @@ if(BUILD_VK_TESTS) corrade_add_test(VkBufferVkTest BufferVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkCommandBufferVkTest CommandBufferVkTest.cpp LIBRARIES MagnumVulkanTester) corrade_add_test(VkCommandPoolVkTest CommandPoolVkTest.cpp LIBRARIES MagnumVulkanTester) - corrade_add_test(VkDescriptorPoolVkTest DescriptorPoolVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) + corrade_add_test(VkDescriptorPoolVkTest DescriptorPoolVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) + corrade_add_test(VkDescriptorSetVkTest DescriptorSetVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkDescriptorSetLayoutVkTest DescriptorSetLayoutVkTest.cpp LIBRARIES MagnumVk MagnumVulkanTester) corrade_add_test(VkDeviceVkTest DeviceVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkDevicePropertiesVkTest DevicePropertiesVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) @@ -252,6 +255,7 @@ if(BUILD_VK_TESTS) VkCommandBufferVkTest VkCommandPoolVkTest VkDescriptorPoolVkTest + VkDescriptorSetVkTest VkDescriptorSetLayoutVkTest VkDeviceVkTest VkDevicePropertiesVkTest diff --git a/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp b/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp index 66a58ba5b..0906edde6 100644 --- a/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp +++ b/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp @@ -23,8 +23,19 @@ DEALINGS IN THE SOFTWARE. */ +#include +#include +#include + #include "Magnum/Vk/DescriptorPoolCreateInfo.h" +#include "Magnum/Vk/DescriptorSet.h" +#include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" #include "Magnum/Vk/DescriptorType.h" +#include "Magnum/Vk/DeviceCreateInfo.h" +#include "Magnum/Vk/DeviceFeatures.h" +#include "Magnum/Vk/DeviceProperties.h" +#include "Magnum/Vk/ExtensionProperties.h" +#include "Magnum/Vk/Extensions.h" #include "Magnum/Vk/Result.h" #include "Magnum/Vk/VulkanTester.h" @@ -33,19 +44,66 @@ namespace Magnum { namespace Vk { namespace Test { namespace { struct DescriptorPoolVkTest: VulkanTester { explicit DescriptorPoolVkTest(); + void setupVariableDescriptorCount(); + void teardown(); + void construct(); void constructMove(); + void allocate(); + void allocateFreeDescriptorSet(); + void allocateFail(); + void allocateVariableCount(); + void allocateVariableCountFreeDescriptorSet(); + void allocateVariableCountFail(); + + void reset(); + void wrap(); + + Queue _queue{NoCreate}; + Device _deviceVariableDescriptorCount{NoCreate}; }; DescriptorPoolVkTest::DescriptorPoolVkTest() { addTests({&DescriptorPoolVkTest::construct, &DescriptorPoolVkTest::constructMove, + &DescriptorPoolVkTest::allocate, + &DescriptorPoolVkTest::allocateFreeDescriptorSet, + &DescriptorPoolVkTest::allocateFail}); + + addTests({&DescriptorPoolVkTest::allocateVariableCount, + &DescriptorPoolVkTest::allocateVariableCountFreeDescriptorSet, + &DescriptorPoolVkTest::allocateVariableCountFail}, + &DescriptorPoolVkTest::setupVariableDescriptorCount, + &DescriptorPoolVkTest::teardown); + + addTests({&DescriptorPoolVkTest::reset, + &DescriptorPoolVkTest::wrap}); } +void DescriptorPoolVkTest::setupVariableDescriptorCount() { + DeviceProperties properties = pickDevice(instance()); + if(!properties.enumerateExtensionProperties().isSupported() || + !(properties.features() & DeviceFeature::DescriptorBindingVariableDescriptorCount)) + return; + + /* Create the device only if not already, to avoid spamming the output */ + if(!_deviceVariableDescriptorCount.handle()) _deviceVariableDescriptorCount.create(instance(), + DeviceCreateInfo{std::move(properties)} + .addQueues(QueueFlag::Graphics, {0.0f}, {_queue}) + .addEnabledExtensions() + .setEnabledFeatures(DeviceFeature::DescriptorBindingVariableDescriptorCount) + ); +} + +void DescriptorPoolVkTest::teardown() { + /* Nothing, the device & queue created by setupVariableDescriptorCount() + is created just once and so shouldn't be destroyed right after */ +} + void DescriptorPoolVkTest::construct() { { DescriptorPool pool{device(), DescriptorPoolCreateInfo{5, { @@ -81,6 +139,176 @@ void DescriptorPoolVkTest::constructMove() { CORRADE_VERIFY(std::is_nothrow_move_assignable::value); } +void DescriptorPoolVkTest::allocate() { + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer}} + }}; + + /* We can allocate two sets at most, each with one uniform buffer */ + DescriptorPool pool{device(), DescriptorPoolCreateInfo{2, { + {DescriptorType::UniformBuffer, 2} + }}}; + + { + Containers::Optional allocated = pool.tryAllocate(layout); + CORRADE_VERIFY(allocated); + CORRADE_VERIFY(allocated->handle()); + /* No DestroyOnDestruction, the sets get freed only on descriptor pool + reset */ + CORRADE_COMPARE(allocated->handleFlags(), HandleFlags{}); + } { + DescriptorSet allocated = pool.allocate(layout); + CORRADE_VERIFY(allocated.handle()); + /* No DestroyOnDestruction, the sets get freed only on descriptor pool + reset */ + CORRADE_COMPARE(allocated.handleFlags(), HandleFlags{}); + } +} + +void DescriptorPoolVkTest::allocateFail() { + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer, 2}}, + }}; + + DescriptorPool pool{device(), DescriptorPoolCreateInfo{1, { + {DescriptorType::UniformBuffer, 1} + }}}; + + { + /* tryAllocate() should not assert, and should not print anything */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!pool.tryAllocate(layout)); + CORRADE_COMPARE(out.str(), ""); + } { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + /* allocate() should assert with ErrorOutOfPoolMemory */ + std::ostringstream out; + Error redirectError{&out}; + pool.allocate(layout); + CORRADE_COMPARE(out.str(), "Vk::DescriptorPool::allocate(): allocation failed with Vk::Result::ErrorOutOfPoolMemory\n"); + } +} + +void DescriptorPoolVkTest::allocateFreeDescriptorSet() { + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer}} + }}; + + DescriptorPool pool{device(), DescriptorPoolCreateInfo{1, { + {DescriptorType::UniformBuffer, 1} + }, DescriptorPoolCreateInfo::Flag::FreeDescriptorSet}}; + + DescriptorSet allocated = pool.allocate(layout); + CORRADE_VERIFY(allocated.handle()); + /* vkFreeDescriptorSets() gets called on destruction */ + CORRADE_COMPARE(allocated.handleFlags(), HandleFlag::DestroyOnDestruction); +} + +void DescriptorPoolVkTest::allocateVariableCount() { + if(!(_deviceVariableDescriptorCount.enabledFeatures() & DeviceFeature::DescriptorBindingVariableDescriptorCount)) + CORRADE_SKIP("DeviceFeature::DescriptorBindingVariableDescriptorCount not supported, can't test."); + + DescriptorSetLayout layout{_deviceVariableDescriptorCount, DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer, 8, ~ShaderStages{}, DescriptorSetLayoutBinding::Flag::VariableDescriptorCount}} + }}; + + /* We can allocate two sets at most and at most 12 uniform buffers */ + DescriptorPool pool{_deviceVariableDescriptorCount, DescriptorPoolCreateInfo{2, { + {DescriptorType::UniformBuffer, 12} + }}}; + + { + Containers::Optional allocated = pool.tryAllocate(layout, 8); + CORRADE_VERIFY(allocated); + CORRADE_VERIFY(allocated->handle()); + /* No DestroyOnDestruction, the sets get freed only on descriptor pool + reset */ + CORRADE_COMPARE(allocated->handleFlags(), HandleFlags{}); + } { + DescriptorSet allocated = pool.allocate(layout, 4); + CORRADE_VERIFY(allocated.handle()); + /* No DestroyOnDestruction, the sets get freed only on descriptor pool + reset */ + CORRADE_COMPARE(allocated.handleFlags(), HandleFlags{}); + } +} + +void DescriptorPoolVkTest::allocateVariableCountFail() { + if(!(_deviceVariableDescriptorCount.enabledFeatures() & DeviceFeature::DescriptorBindingVariableDescriptorCount)) + CORRADE_SKIP("DeviceFeature::DescriptorBindingVariableDescriptorCount not supported, can't test."); + + DescriptorSetLayout layout{_deviceVariableDescriptorCount, DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer, 8, ~ShaderStages{}, DescriptorSetLayoutBinding::Flag::VariableDescriptorCount}} + }}; + + /* We can allocate two sets at most and at most 8 uniform buffers */ + DescriptorPool pool{_deviceVariableDescriptorCount, DescriptorPoolCreateInfo{2, { + {DescriptorType::UniformBuffer, 7} + }}}; + + { + /* tryAllocate() should not assert, and should not print anything */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!pool.tryAllocate(layout, 8)); + CORRADE_COMPARE(out.str(), ""); + } { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + /* allocate() should assert with ErrorOutOfPoolMemory */ + std::ostringstream out; + Error redirectError{&out}; + pool.allocate(layout, 8); + CORRADE_COMPARE(out.str(), "Vk::DescriptorPool::allocate(): allocation failed with Vk::Result::ErrorOutOfPoolMemory\n"); + } +} + +void DescriptorPoolVkTest::allocateVariableCountFreeDescriptorSet() { + if(!(_deviceVariableDescriptorCount.enabledFeatures() & DeviceFeature::DescriptorBindingVariableDescriptorCount)) + CORRADE_SKIP("DeviceFeature::DescriptorBindingVariableDescriptorCount not supported, can't test."); + + DescriptorSetLayout layout{_deviceVariableDescriptorCount, DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer, 4, ~ShaderStages{}, DescriptorSetLayoutBinding::Flag::VariableDescriptorCount}} + }}; + + DescriptorPool pool{_deviceVariableDescriptorCount, DescriptorPoolCreateInfo{1, { + {DescriptorType::UniformBuffer, 4} + }, DescriptorPoolCreateInfo::Flag::FreeDescriptorSet}}; + + DescriptorSet allocated = pool.allocate(layout, 4); + CORRADE_VERIFY(allocated.handle()); + /* vkFreeDescriptorSets() gets called on destruction */ + CORRADE_COMPARE(allocated.handleFlags(), HandleFlag::DestroyOnDestruction); +} + +void DescriptorPoolVkTest::reset() { + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer}} + }}; + + /* Just one */ + DescriptorPool pool{device(), DescriptorPoolCreateInfo{1, { + {DescriptorType::UniformBuffer, 1} + }}}; + + /* First allocation will work */ + CORRADE_VERIFY(pool.tryAllocate(layout)); + + /* Second won't */ + CORRADE_VERIFY(!pool.tryAllocate(layout)); + + pool.reset(); + + /* Now it will again */ + CORRADE_VERIFY(pool.tryAllocate(layout)); +} + void DescriptorPoolVkTest::wrap() { VkDescriptorPool pool{}; CORRADE_COMPARE(Result(device()->CreateDescriptorPool(device(), diff --git a/src/Magnum/Vk/Test/DescriptorSetTest.cpp b/src/Magnum/Vk/Test/DescriptorSetTest.cpp new file mode 100644 index 000000000..0a07e5120 --- /dev/null +++ b/src/Magnum/Vk/Test/DescriptorSetTest.cpp @@ -0,0 +1,62 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 +#include + +#include "Magnum/Vk/DescriptorSet.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DescriptorSetTest: TestSuite::Tester { + explicit DescriptorSetTest(); + + void constructNoCreate(); + void constructCopy(); +}; + +DescriptorSetTest::DescriptorSetTest() { + addTests({&DescriptorSetTest::constructNoCreate, + &DescriptorSetTest::constructCopy}); +} + +void DescriptorSetTest::constructNoCreate() { + { + DescriptorSet set{NoCreate}; + CORRADE_VERIFY(!set.handle()); + } + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + +void DescriptorSetTest::constructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DescriptorSetTest) diff --git a/src/Magnum/Vk/Test/DescriptorSetVkTest.cpp b/src/Magnum/Vk/Test/DescriptorSetVkTest.cpp new file mode 100644 index 000000000..11654e3a9 --- /dev/null +++ b/src/Magnum/Vk/Test/DescriptorSetVkTest.cpp @@ -0,0 +1,110 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 "Magnum/Vk/DescriptorPoolCreateInfo.h" +#include "Magnum/Vk/DescriptorSet.h" +#include "Magnum/Vk/DescriptorSetLayoutCreateInfo.h" +#include "Magnum/Vk/DescriptorType.h" +#include "Magnum/Vk/Result.h" +#include "Magnum/Vk/VulkanTester.h" + +namespace Magnum { namespace Vk { namespace Test { namespace { + +struct DescriptorSetVkTest: VulkanTester { + explicit DescriptorSetVkTest(); + + void constructMove(); + + void wrap(); +}; + +DescriptorSetVkTest::DescriptorSetVkTest() { + addTests({&DescriptorSetVkTest::constructMove, + + &DescriptorSetVkTest::wrap}); +} + +void DescriptorSetVkTest::constructMove() { + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer}} + }}; + + /* Use the FreeDescriptorSet flag so the allocated descriptor set has + DestroyOnDestruction set */ + DescriptorPool pool{device(), DescriptorPoolCreateInfo{1, { + {DescriptorType::UniformBuffer, 1} + }, DescriptorPoolCreateInfo::Flag::FreeDescriptorSet}}; + + DescriptorSet a = pool.allocate(layout); + VkDescriptorSet handle = a.handle(); + + DescriptorSet b = std::move(a); + CORRADE_VERIFY(!a.handle()); + CORRADE_COMPARE(b.handle(), handle); + CORRADE_COMPARE(b.handleFlags(), HandleFlag::DestroyOnDestruction); + + DescriptorSet c{NoCreate}; + c = std::move(b); + CORRADE_VERIFY(!b.handle()); + CORRADE_COMPARE(b.handleFlags(), HandleFlags{}); + CORRADE_COMPARE(c.handle(), handle); + CORRADE_COMPARE(c.handleFlags(), HandleFlag::DestroyOnDestruction); + + CORRADE_VERIFY(std::is_nothrow_move_constructible::value); + CORRADE_VERIFY(std::is_nothrow_move_assignable::value); +} + +void DescriptorSetVkTest::wrap() { + DescriptorSetLayout layout{device(), DescriptorSetLayoutCreateInfo{ + {{0, DescriptorType::UniformBuffer}} + }}; + + /* Use the FreeDescriptorSet flag so we can explicitly free the thing */ + DescriptorPool pool{device(), DescriptorPoolCreateInfo{1, { + {DescriptorType::UniformBuffer, 1} + }, DescriptorPoolCreateInfo::Flag::FreeDescriptorSet}}; + + VkDescriptorSetAllocateInfo info{}; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + info.descriptorPool = pool; + info.descriptorSetCount = 1; + const VkDescriptorSetLayout handle = layout; + info.pSetLayouts = &handle; /* ew */ + VkDescriptorSet set{}; + CORRADE_COMPARE(Result(device()->AllocateDescriptorSets(device(), + &info, &set)), Result::Success); + + auto wrapped = DescriptorSet::wrap(device(), pool, set, HandleFlag::DestroyOnDestruction); + CORRADE_COMPARE(wrapped.handle(), set); + + /* Release the handle again, destroy by hand */ + CORRADE_COMPARE(wrapped.release(), set); + CORRADE_VERIFY(!wrapped.handle()); + device()->FreeDescriptorSets(device(), pool, 1, &set); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Vk::Test::DescriptorSetVkTest) diff --git a/src/Magnum/Vk/Vk.h b/src/Magnum/Vk/Vk.h index 723772562..913abbe59 100644 --- a/src/Magnum/Vk/Vk.h +++ b/src/Magnum/Vk/Vk.h @@ -59,6 +59,7 @@ enum class DependencyFlag: UnsignedInt; typedef Containers::EnumSet DependencyFlags; class DescriptorPool; class DescriptorPoolCreateInfo; +class DescriptorSet; class DescriptorSetLayout; class DescriptorSetLayoutCreateInfo; enum class DescriptorType: Int; From 2b7ca726f1f6a65b8cde6ad05004a02c86f002eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 15 Mar 2021 17:29:59 +0100 Subject: [PATCH 097/161] Vk: document why certain extensions are implicitly enabled. --- src/Magnum/Vk/Device.cpp | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp index 285a01635..6ad2f34d0 100644 --- a/src/Magnum/Vk/Device.cpp +++ b/src/Magnum/Vk/Device.cpp @@ -180,37 +180,44 @@ DeviceCreateInfo::DeviceCreateInfo(DeviceProperties& deviceProperties, const Ext /* Only if we don't have Vulkan 1.1, on which these are core */ if(_state->version < Version::Vk11) { + /* Used for the extra extension points in MemoryAllocationInfo */ if(extensionProperties->isSupported()) addEnabledExtensions(); + + /* Used for the extra extension points in bindMemory() */ if(extensionProperties->isSupported()) addEnabledExtensions(); } + /* Only if we don't have Vulkan 1.2, on which these are core */ if(_state->version < Version::Vk12) { + /* Used for the extra extension points in RenderPassCreateInfo and + related structs */ if(extensionProperties->isSupported()) addEnabledExtensions(); } - /* Enable the KHR_copy_commands2 and EXT_extended_dynamic_state - extensions. Not in any Vulkan version yet. */ + /* Used for the extra extension points in CopyBuffer, CopyImage etc. + Not in any Vulkan version yet. */ if(extensionProperties->isSupported()) addEnabledExtensions(); + + /* Used for dynamic stride and primitive specification in + CommandBuffer::draw(). Not in any Vulkan version yet. */ if(extensionProperties->isSupported()) addEnabledExtensions(); - /* Enable the KHR_portability_subset extension, which *has to be* - enabled when available. Not enabling any of its features though, - that responsibility lies on the user. */ + /* The KHR_portability_subset extension *has to be* enabled when + available. Not enabling any of its features though, that + responsibility lies on the user. If KHR_portability_subset is not + supported, mark its features as *implicitly* supported -- those + don't get explicitly enabled and are also not listed in the list of + enabled features in the startup log */ if(extensionProperties->isSupported()) { addEnabledExtensions(); - - /* Otherwise, if KHR_portability_subset is not supported, mark its - features as *implicitly* supported -- those don't get explicitly - enabled and are also not listed in the list of enabled features in - the startup log */ - /** @todo wrap this under a NoImplicitFeatures flag? it doesn't actually - *do* anything though */ } else { + /** @todo wrap this under a NoImplicitFeatures flag? it doesn't + actually *do* anything though */ _state->implicitFeatures = Implementation::deviceFeaturesPortabilitySubset(); } } From baaa083af8576f8a9db06e537397b345b8af4f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 15 Mar 2021 17:31:29 +0100 Subject: [PATCH 098/161] Vk: implicitly enable VK_KHR_maintenance1. --- package/archlinux/PKGBUILD | 2 +- package/archlinux/PKGBUILD-coverage | 2 +- package/archlinux/PKGBUILD-release | 2 +- package/ci/unix-desktop-vulkan.sh | 2 +- src/Magnum/Vk/Device.cpp | 5 +++++ 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/package/archlinux/PKGBUILD b/package/archlinux/PKGBUILD index aee3fa08d..978ec8a2c 100644 --- a/package/archlinux/PKGBUILD +++ b/package/archlinux/PKGBUILD @@ -78,7 +78,7 @@ check() { MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest for device in "" cpu; do MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest - MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest + MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest done } diff --git a/package/archlinux/PKGBUILD-coverage b/package/archlinux/PKGBUILD-coverage index 4876fd7b9..ddc4e0ac7 100644 --- a/package/archlinux/PKGBUILD-coverage +++ b/package/archlinux/PKGBUILD-coverage @@ -79,7 +79,7 @@ check() { MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true for device in "" cpu; do MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true - MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true + MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true done ./Debug/bin/magnum-al-info > /dev/null diff --git a/package/archlinux/PKGBUILD-release b/package/archlinux/PKGBUILD-release index d311c359a..0ddd0a3ff 100644 --- a/package/archlinux/PKGBUILD-release +++ b/package/archlinux/PKGBUILD-release @@ -116,7 +116,7 @@ check() { MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest for device in "" cpu; do MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest - MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest + MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest done done } diff --git a/package/ci/unix-desktop-vulkan.sh b/package/ci/unix-desktop-vulkan.sh index c15d48445..ce4d0dd72 100755 --- a/package/ci/unix-desktop-vulkan.sh +++ b/package/ci/unix-desktop-vulkan.sh @@ -77,7 +77,7 @@ export CORRADE_TEST_COLOR=ON # Keep in sync with PKGBUILD, PKGBUILD-coverage and PKGBUILD-release ctest -V MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest -MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest +MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest # Test install, after running the tests as for them it shouldn't be needed ninja install diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp index 6ad2f34d0..81a6ca729 100644 --- a/src/Magnum/Vk/Device.cpp +++ b/src/Magnum/Vk/Device.cpp @@ -180,6 +180,11 @@ DeviceCreateInfo::DeviceCreateInfo(DeviceProperties& deviceProperties, const Ext /* Only if we don't have Vulkan 1.1, on which these are core */ if(_state->version < Version::Vk11) { + /* Needed for VK_ERROR_OUT_OF_POOL_MEMORY support in DescriptorSet + allocation */ + if(extensionProperties->isSupported()) + addEnabledExtensions(); + /* Used for the extra extension points in MemoryAllocationInfo */ if(extensionProperties->isSupported()) addEnabledExtensions(); From 4cc1bf11b71d78a7dd054da8c5925ffb34968095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 15 Mar 2021 17:32:56 +0100 Subject: [PATCH 099/161] Vk: add a trivial test for Mesh move/copy. --- src/Magnum/Vk/Test/MeshTest.cpp | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Magnum/Vk/Test/MeshTest.cpp b/src/Magnum/Vk/Test/MeshTest.cpp index f8af4f3d3..25c429a89 100644 --- a/src/Magnum/Vk/Test/MeshTest.cpp +++ b/src/Magnum/Vk/Test/MeshTest.cpp @@ -42,7 +42,9 @@ struct MeshTest: TestSuite::Tester { void mapIndexTypeInvalid(); void construct(); - void countsOffsets(); + void constructCountsOffsets(); + void constructCopy(); + void constructMove(); void addVertexBuffer(); void addVertexBufferOwned(); @@ -61,7 +63,9 @@ MeshTest::MeshTest() { &MeshTest::mapIndexTypeInvalid, &MeshTest::construct, - &MeshTest::countsOffsets, + &MeshTest::constructCountsOffsets, + &MeshTest::constructCopy, + &MeshTest::constructMove, &MeshTest::addVertexBuffer, &MeshTest::addVertexBufferOwned, @@ -124,7 +128,7 @@ void MeshTest::construct() { CORRADE_VERIFY(!mesh.isIndexed()); } -void MeshTest::countsOffsets() { +void MeshTest::constructCountsOffsets() { Mesh mesh{MeshLayout{MeshPrimitive::Triangles}}; mesh.setCount(15) .setVertexOffset(3) @@ -138,6 +142,26 @@ void MeshTest::countsOffsets() { CORRADE_COMPARE(mesh.instanceOffset(), 9); } +void MeshTest::constructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +void MeshTest::constructMove() { + /* The move is defaulted, so test just the very basics */ + Mesh a{MeshLayout{MeshPrimitive::Triangles}}; + a.setCount(15); + + Mesh b = std::move(a); + CORRADE_COMPARE(b.layout().vkPipelineInputAssemblyStateCreateInfo().topology, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + CORRADE_COMPARE(b.count(), 15); + + Mesh c{MeshLayout{MeshPrimitive::Points}}; + c = std::move(b); + CORRADE_COMPARE(c.layout().vkPipelineInputAssemblyStateCreateInfo().topology, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + CORRADE_COMPARE(c.count(), 15); +} + void MeshTest::addVertexBuffer() { Mesh mesh{MeshLayout{MeshPrimitive::TriangleFan} .addBinding(1, 2) From 1e7fafdd75d09a8b7ecf0f3625fa0074be95da52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 15 Mar 2021 17:42:31 +0100 Subject: [PATCH 100/161] Vk: VK_KHR_create_renderpass depends on KHR_maintenance2 and multiview. The validation layer complained. So enable these two implicitly as well if we're on 1.0. And since those are now disabled in certain test runs to test related code paths, DeviceVkTest needs to be updated to skip affected tests if this happens. --- package/archlinux/PKGBUILD | 2 +- package/archlinux/PKGBUILD-coverage | 2 +- package/archlinux/PKGBUILD-release | 2 +- package/ci/unix-desktop-vulkan.sh | 2 +- src/Magnum/Vk/Device.cpp | 11 ++++++++++- src/Magnum/Vk/Test/DeviceVkTest.cpp | 3 +++ 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/package/archlinux/PKGBUILD b/package/archlinux/PKGBUILD index 978ec8a2c..4a962d6b5 100644 --- a/package/archlinux/PKGBUILD +++ b/package/archlinux/PKGBUILD @@ -78,7 +78,7 @@ check() { MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest for device in "" cpu; do MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest - MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest + MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1 VK_KHR_multiview VK_KHR_maintenance2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest done } diff --git a/package/archlinux/PKGBUILD-coverage b/package/archlinux/PKGBUILD-coverage index ddc4e0ac7..43d54ff3c 100644 --- a/package/archlinux/PKGBUILD-coverage +++ b/package/archlinux/PKGBUILD-coverage @@ -79,7 +79,7 @@ check() { MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true for device in "" cpu; do MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true - MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true + MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1 VK_KHR_multiview VK_KHR_maintenance2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest || true done ./Debug/bin/magnum-al-info > /dev/null diff --git a/package/archlinux/PKGBUILD-release b/package/archlinux/PKGBUILD-release index 0ddd0a3ff..f3ff212c5 100644 --- a/package/archlinux/PKGBUILD-release +++ b/package/archlinux/PKGBUILD-release @@ -116,7 +116,7 @@ check() { MAGNUM_DEVICE=cpu CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest for device in "" cpu; do MAGNUM_DEVICE=$device MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest - MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest + MAGNUM_DEVICE=$device MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1 VK_KHR_multiview VK_KHR_maintenance2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON CORRADE_TEST_COLOR=ON ctest --output-on-failure -j5 -R VkTest done done } diff --git a/package/ci/unix-desktop-vulkan.sh b/package/ci/unix-desktop-vulkan.sh index ce4d0dd72..c57021c4e 100755 --- a/package/ci/unix-desktop-vulkan.sh +++ b/package/ci/unix-desktop-vulkan.sh @@ -77,7 +77,7 @@ export CORRADE_TEST_COLOR=ON # Keep in sync with PKGBUILD, PKGBUILD-coverage and PKGBUILD-release ctest -V MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest -MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest +MAGNUM_DISABLE_EXTENSIONS="VK_KHR_get_physical_device_properties2 VK_KHR_get_memory_requirements2 VK_KHR_bind_memory2 VK_KHR_create_renderpass2 VK_KHR_copy_commands2 VK_KHR_maintenance1 VK_KHR_multiview VK_KHR_maintenance2" MAGNUM_VULKAN_VERSION=1.0 CORRADE_TEST_SKIP_BENCHMARKS=ON ctest -V -R VkTest # Test install, after running the tests as for them it shouldn't be needed ninja install diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp index 81a6ca729..1546130fc 100644 --- a/src/Magnum/Vk/Device.cpp +++ b/src/Magnum/Vk/Device.cpp @@ -185,6 +185,14 @@ DeviceCreateInfo::DeviceCreateInfo(DeviceProperties& deviceProperties, const Ext if(extensionProperties->isSupported()) addEnabledExtensions(); + /* Dependencies of VK_KHR_create_renderpass2, which is enabled + below. If an extension is supported, all its dependencies should + be too, so not checking for their presence again. */ + if(extensionProperties->isSupported()) { + addEnabledExtensions(); + addEnabledExtensions(); + } + /* Used for the extra extension points in MemoryAllocationInfo */ if(extensionProperties->isSupported()) addEnabledExtensions(); @@ -197,7 +205,8 @@ DeviceCreateInfo::DeviceCreateInfo(DeviceProperties& deviceProperties, const Ext /* Only if we don't have Vulkan 1.2, on which these are core */ if(_state->version < Version::Vk12) { /* Used for the extra extension points in RenderPassCreateInfo and - related structs */ + related structs. Depends on VK_KHR_multiview and + VK_KHR_maintenance2, which were enabled above. */ if(extensionProperties->isSupported()) addEnabledExtensions(); } diff --git a/src/Magnum/Vk/Test/DeviceVkTest.cpp b/src/Magnum/Vk/Test/DeviceVkTest.cpp index 1cf2e8787..7f5be25f5 100644 --- a/src/Magnum/Vk/Test/DeviceVkTest.cpp +++ b/src/Magnum/Vk/Test/DeviceVkTest.cpp @@ -277,6 +277,9 @@ void DeviceVkTest::createInfoExtensions() { } void DeviceVkTest::createInfoExtensionsCopiedStrings() { + if(std::getenv("MAGNUM_DISABLE_EXTENSIONS")) + CORRADE_SKIP("Can't test with the MAGNUM_DISABLE_EXTENSIONS environment variable set"); + Containers::StringView globalButNotNullTerminated = "VK_KHR_maintenance25"_s.except(1); Containers::String localButNullTerminated = Extensions::KHR::draw_indirect_count::string(); From f41ea6bbebd0087cccc5578719677e0bf0894321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 15 Mar 2021 17:43:23 +0100 Subject: [PATCH 101/161] Vk: enable KHR_maintenance3 in a test. The validation layer complained here as well. --- src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp b/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp index 0906edde6..98460a223 100644 --- a/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp +++ b/src/Magnum/Vk/Test/DescriptorPoolVkTest.cpp @@ -94,7 +94,13 @@ void DescriptorPoolVkTest::setupVariableDescriptorCount() { if(!_deviceVariableDescriptorCount.handle()) _deviceVariableDescriptorCount.create(instance(), DeviceCreateInfo{std::move(properties)} .addQueues(QueueFlag::Graphics, {0.0f}, {_queue}) - .addEnabledExtensions() + .addEnabledExtensions< + /* Dependency of EXT_descriptor_indexing if 1.1 isn't + supported. For simpler handling we enable it always, instead + of only when we're on 1.0. */ + Extensions::KHR::maintenance3, + Extensions::EXT::descriptor_indexing + >() .setEnabledFeatures(DeviceFeature::DescriptorBindingVariableDescriptorCount) ); } From 28a2cb85676ec808b21e4b690d2e1fd9e25be341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Mar 2021 18:03:11 +0100 Subject: [PATCH 102/161] Vk: interesting inconsistency with std::initializer_list. I can't trust anything in this language. SIGH. --- src/Magnum/Vk/DescriptorPool.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Magnum/Vk/DescriptorPool.cpp b/src/Magnum/Vk/DescriptorPool.cpp index 2feeb1f75..aca95238e 100644 --- a/src/Magnum/Vk/DescriptorPool.cpp +++ b/src/Magnum/Vk/DescriptorPool.cpp @@ -40,7 +40,10 @@ namespace Magnum { namespace Vk { DescriptorPoolCreateInfo::DescriptorPoolCreateInfo(const UnsignedInt maxSets, const Containers::ArrayView> poolSizes, const Flags flags): _info{} { CORRADE_ASSERT(maxSets, "Vk::DescriptorPoolCreateInfo: there has to be at least one set", ); - CORRADE_ASSERT(poolSizes, + /* On certain compilers, {} (empty initializer list) gets converted to an + arrayview that's not null, interesting. Explicitly using .empty() to + ensure the assert gets properly fired. */ + CORRADE_ASSERT(!poolSizes.empty(), "Vk::DescriptorPoolCreateInfo: there has to be at least one pool", ); Containers::ArrayView poolSizesCopy; From 807c337db1de816e250103ec6713354adf1ef352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Mar 2021 18:07:19 +0100 Subject: [PATCH 103/161] Trade: adapt to CORRADE_ALIGNAS() deprecation. --- src/Magnum/Trade/MaterialData.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Trade/MaterialData.h b/src/Magnum/Trade/MaterialData.h index 5344d0fb5..6e716c2e2 100644 --- a/src/Magnum/Trade/MaterialData.h +++ b/src/Magnum/Trade/MaterialData.h @@ -1320,7 +1320,7 @@ class MAGNUM_TRADE_EXPORT MaterialAttributeData { char name[Implementation::MaterialAttributeDataSize - sizeof(MaterialAttributeType) - sizeof(T)]; T value; }; - union CORRADE_ALIGNAS(8) Storage { + union alignas(8) Storage { constexpr explicit Storage() noexcept: data{} {} constexpr explicit Storage(Containers::StringView name, Containers::StringView value) noexcept: s{MaterialAttributeType::String, name, value} {} From f0f8dce55967505aecd68f2f2f59e2ec6e1a759b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Mar 2021 18:07:35 +0100 Subject: [PATCH 104/161] Math: link relevant APIs in Quaternion multiply docs. --- src/Magnum/Math/Quaternion.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Magnum/Math/Quaternion.h b/src/Magnum/Math/Quaternion.h index 1dd62bc14..f4b0708ef 100644 --- a/src/Magnum/Math/Quaternion.h +++ b/src/Magnum/Math/Quaternion.h @@ -548,6 +548,9 @@ template class Quaternion { * p q = [p_S \boldsymbol q_V + q_S \boldsymbol p_V + \boldsymbol p_V \times \boldsymbol q_V, * p_S q_S - \boldsymbol p_V \cdot \boldsymbol q_V] * @f] + * + * @see @ref cross(const Vector3&, const Vector3&), + * @ref Vector::dot() const */ Quaternion operator*(const Quaternion& other) const; From 7154200e16472e6f663e222cffc60533693e8180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Mar 2021 18:07:54 +0100 Subject: [PATCH 105/161] doc: the year wasn't updated here. --- doc/mainpage.dox | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 5a1b5ae99..4d4598523 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -85,7 +85,8 @@ Magnum is licensed under the MIT/Expat license: > > Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, -> 2020 Vladimír Vondruš <mosra@centrum.cz> and contributors +> 2020, 2021 +> Vladimír Vondruš <mosra@centrum.cz> and contributors > > Permission is hereby granted, free of charge, to any person obtaining a > copy of this software and associated documentation files (the "Software"), From 315e31476ad06c6584553f90417a8dc901264522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Mar 2021 18:10:17 +0100 Subject: [PATCH 106/161] GL: fix out of bounds accesses in Shader limit queries. Sigh, it really took quite a while (half a decade??) to discover and fix this. --- doc/changelog.dox | 3 +++ src/Magnum/GL/Implementation/ShaderState.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 5fa71864d..e90a5b477 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -337,6 +337,9 @@ See also: accident and it was also not really moving everything properly, especially when delayed creation was done on the moved-to object - @ref GL::Renderer::MemoryBarrier::ShaderStorage had an incorrect value +- @ref GL::Shader limit queries for a particular shader stage on desktop were + out-of-bounds array accesses, causing wrong or random values being returned + for most shader-related limits - Fixed assertions related to OpenGL driver workarounds when the proprietary AMDGPU PRO drivers are used on Linux - @ref Platform::EmscriptenApplication randomly created antialiased contexts diff --git a/src/Magnum/GL/Implementation/ShaderState.h b/src/Magnum/GL/Implementation/ShaderState.h index 1cd83ef77..867d6bc2b 100644 --- a/src/Magnum/GL/Implementation/ShaderState.h +++ b/src/Magnum/GL/Implementation/ShaderState.h @@ -45,7 +45,7 @@ struct ShaderState { enum: std::size_t { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - StageCount = 4 + StageCount = 6 #else StageCount = 2 #endif From 18817ed58aca5036c88aae98a60e64356e2827b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 24 Mar 2021 20:22:02 +0100 Subject: [PATCH 107/161] Vk: hello, MinGW, why are you so special again?! --- src/Magnum/Vk/Assert.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Magnum/Vk/Assert.h b/src/Magnum/Vk/Assert.h index ca8305779..d92948c01 100644 --- a/src/Magnum/Vk/Assert.h +++ b/src/Magnum/Vk/Assert.h @@ -108,6 +108,9 @@ including the @ref Magnum/Vk/Assert.h header. return Magnum::Vk::Result(call); \ }() #elif defined(CORRADE_STANDARD_ASSERT) +/* MinGW GCC 8 for some reason needs the `return Magnum::Vk::Result();` at the + end, otherwise it complains about non-void function exiting with no return. + All other compilers understand the abort() as a noreturn function. */ #define MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(call, ...) \ [&]() { \ const Magnum::Vk::Result _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) = Magnum::Vk::Result(call); \ @@ -116,6 +119,7 @@ including the @ref Magnum/Vk/Assert.h header. return _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__); \ } \ assert(false); \ + return Magnum::Vk::Result(); \ }() #else #define MAGNUM_VK_INTERNAL_ASSERT_SUCCESS_OR(call, ...) \ @@ -127,6 +131,7 @@ including the @ref Magnum/Vk/Assert.h header. } \ Corrade::Utility::Error{Corrade::Utility::Error::defaultOutput()} << "Call " #call " failed with" << _CORRADE_HELPER_PASTE(magnumVkResult, __LINE__) << "at " __FILE__ ":" CORRADE_LINE_STRING; \ std::abort(); \ + return Magnum::Vk::Result(); \ }() #endif #endif From bc0bb075aba1552f30a3382d315c55384ab94d8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 29 Mar 2021 18:07:33 +0200 Subject: [PATCH 108/161] Update Android installation layout to better comply with NDK r19+. And take CMake 3.20 into account. --- CMakeLists.txt | 20 ++++--- doc/building.dox | 72 +++++++++++++++--------- doc/changelog.dox | 8 +++ doc/platforms-android.dox | 40 +++++++++---- modules/FindCorrade.cmake | 12 ++-- modules/FindMagnum.cmake | 22 +++++--- package/archlinux/PKGBUILD-android-arm64 | 7 +-- 7 files changed, 115 insertions(+), 66 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f5f7ef9ed..593c31166 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,8 +183,6 @@ endif() set(MAGNUM_DEPLOY_PREFIX "." CACHE STRING "Prefix where to put final application executables") -set(MAGNUM_INCLUDE_INSTALL_PREFIX "." - CACHE STRING "Prefix where to put platform-independent include and other files") option(BUILD_STATIC "Build static libraries (default are shared)" OFF) # Disable PIC on Emscripten by default (but still allow it to be enabled @@ -341,11 +339,19 @@ endif() include(${CORRADE_LIB_SUFFIX_MODULE}) set(MAGNUM_BINARY_INSTALL_DIR bin) set(MAGNUM_LIBRARY_INSTALL_DIR lib${LIB_SUFFIX}) -set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/share/magnum) -set(MAGNUM_CMAKE_MODULE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/share/cmake/Magnum) -set(MAGNUM_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/Magnum) -set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/MagnumExternal) -set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/MagnumPlugins) +set(MAGNUM_DATA_INSTALL_DIR share/magnum) +set(MAGNUM_CMAKE_MODULE_INSTALL_DIR share/cmake/Magnum) +set(MAGNUM_INCLUDE_INSTALL_DIR include/Magnum) +set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR include/MagnumExternal) +set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR include/MagnumPlugins) +if(MAGNUM_BUILD_DEPRECATED AND MAGNUM_INCLUDE_INSTALL_PREFIX AND NOT MAGNUM_INCLUDE_INSTALL_PREFIX STREQUAL ".") + message(DEPRECATION "MAGNUM_INCLUDE_INSTALL_PREFIX is obsolete as its primary use was for old Android NDK versions. Please switch to the NDK r19+ layout instead of using this variable and recreate your build directory to get rid of this warning.") + set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_DATA_INSTALL_DIR}) + set(MAGNUM_CMAKE_MODULE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_CMAKE_MODULE_INSTALL_DIR}) + set(MAGNUM_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_INCLUDE_INSTALL_DIR}) + set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR}) + set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}) +endif() # Separate install dirs for debug and release plugins set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-d) diff --git a/doc/building.dox b/doc/building.dox index 7b57d18a8..a2baba56e 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -698,20 +698,29 @@ installed files. The following variables are supported: - `LIB_SUFFIX` --- Setting this variable to `64` can be used to tell CMake to install to `lib64/` instead of `lib/`. In most cases this variable is - autodetected, so you don't need to set it yourself. + autodetected, so you don't need to set it yourself. On + @ref CORRADE_TARGET_ANDROID "Android", if `CMAKE_INSTALL_PREFIX` points to + the NDK sysroot, it gets automatically set to + `/${CMAKE_ANDROID_ARCH_TRIPLE}/${CMAKE_SYSTEM_VERSION}` to put the binaries + to correct location for given architecture and API level version. - `MAGNUM_DEPLOY_PREFIX` --- Used on @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten" to override location where web demos and utilities (such as @ref magnum-gl-info) are installed, so you can have libraries installed to a system location and utilities to your webserver, for example. Defaults to ``.``. If a relative path is used, it's relative to `CMAKE_INSTALL_PREFIX`. -- `MAGNUM_INCLUDE_INSTALL_PREFIX` --- Used on @ref CORRADE_TARGET_ANDROID "Android" - to override location where platform-independent include files, CMake - scripts and other files are installed. CMake on Android by default searches - for binaries in <ndk>/platforms/android-<api>/arch-<arch>/usr - based on target API and platform, but looks for headers in a central - location at <ndk>/toolchains/llvm/prebuilt/<host>/sysroot/usr. - Defaults to ``.``. If a relative path is used, it's relative to - `CMAKE_INSTALL_PREFIX`. + +The following variables are deprecated and provided only for backwards +compatibility if `BUILD_DEPRECATED` isn't disabled. + +- `MAGNUM_INCLUDE_INSTALL_PREFIX` --- Overrides location where + platform-independent include files, CMake scripts and other files are + installed. For NDK versions before r19, CMake on Android by default + searched for binaries in <ndk>/platforms/android-<api>/arch-<arch>/usr + based on target API and platform, but for headers in a central location at + <ndk>/toolchains/llvm/prebuilt/<host>/sysroot/usr and + this was used to handle that case. Nowadays please use NDK r19 and newer, + with the unified sysroot layout. Defaults to ``.``. If a relative path is + used, it's relative to `CMAKE_INSTALL_PREFIX`. Various plugin interfaces search for plugins in locations and order documented in @ref Corrade::PluginManager::implicitPluginSearchPaths(), @@ -1059,22 +1068,33 @@ Create a build directory and run `cmake` and the build command in it. Set ABI. Check the [CMake Android cross-compiling documentation](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android) for further information. You can omit specifying `CORRADE_RC_EXECUTABLE` if @ref building-cross-corrade-rc "natively-built corrade-rc" is accessible -through `PATH`. +through `PATH`. Note that `BUILD_STATIC` is implicitly enabled, because +manually loading all depending shared libraries using JNI would be too +inconvenient. The engine is built for OpenGL ES 2.0 by default, switch to 3.0 +by disabling `TARGET_GLES2`. If you set `CMAKE_INSTALL_PREFIX` to `/usr` subdirectory of the particular -Android platform sysroot, the package will get found automatically when -compiling depending projects. Gradle and other Android buildsystems expect -platform-independent includes and other files to be stored in a central -location, you can point `MAGNUM_INCLUDE_INSTALL_PREFIX` there to install the -includes separately. Another option is to explicitly set `CMAKE_PREFIX_PATH` -to the install location in depending projects. Unfortunately, CMake needs extra -help with `CMAKE_FIND_ROOT_PATH` to correctly find Android libraries, otherwise -it falls back to looking in native system locations. Adapt them to your -system, Android ABI and version and NDK location as needed. - -Note that `BUILD_STATIC` is implicitly enabled, because manually loading all -depending shared libraries using JNI would be too inconvenient. The engine is -built for OpenGL ES 2.0 by default, switch to 3.0 by disabling `TARGET_GLES2`. +Android platform sysroot (as shown below), Magnum's buildsystem will also pick +a `LIB_SUFFIX` corresponding to a particular ABI and version, which in turn +makes the package automatically discoverable when compiling depending projects, +both with vanilla CMake and with Gradle. Another option is to explicitly set +`CMAKE_PREFIX_PATH` to the install location in depending projects. + + + +@m_class{m-note m-warning} + +@par + Unfortunately, CMake before version 3.20 needs extra help with + `CMAKE_FIND_ROOT_PATH` and `CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` to + correctly find Android libraries, as shown below. Otherwise it falls back + to looking in native system locations. Adapt them to your system, Android + ABI and version and NDK location as needed. +@par + CMake 3.20 and newer [is now able to detect everything on its own](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5357) + and you don't need to supply these anymore. + + @m_class{m-console-wrap} @@ -1086,10 +1106,10 @@ cmake .. \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-24/arch-arm64/usr \ - -DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ + -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \ + -DCMAKE_FIND_ROOT_PATH=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot \ + -DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/aarch64-linux-android/24 \ -DCORRADE_RC_EXECUTABLE=/path/to/corrade-rc \ - -DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \ -DTARGET_GLES2=OFF \ -DWITH_ANDROIDAPPLICATION=ON cmake --build . diff --git a/doc/changelog.dox b/doc/changelog.dox index e90a5b477..b94e6c63d 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -330,6 +330,14 @@ See also: - The `FindSDL2.cmake` module was updated to allow using SDL2 as a subproject. See the @ref Platform-Sdl2Application-usage "Platform::Sdl2Application docs" for more information. See also [mosra/magnum#496](https://github.com/mosra/magnum/issues/496). +- With CMake 3.20 and newer it's possible to compile for Android NDK r19+ + without explicitly supplying various system paths. Additionally, when `CMAKE_INSTALL_PREFIX` points to Android NDK sysroot, the `LIB_SUFFIX` + gets autodetected to a correct triplet + API level version subdirectory, + making the installed project discoverable by both vanilla CMake and Gradle. + On CMake 3.16 to 3.19 it's required to set two extra variables for the + same effect. See @ref building-cross-android, @ref platforms-android and + [mosra/magnum#310](https://github.com/mosra/magnum/issues/310) for more + information. @subsection changelog-latest-bugfixes Bug fixes diff --git a/doc/platforms-android.dox b/doc/platforms-android.dox index 629f62020..5be3d9997 100644 --- a/doc/platforms-android.dox +++ b/doc/platforms-android.dox @@ -70,10 +70,22 @@ different. Android allows to run arbitrary console utilities and tests via ADB. Assuming you have Magnum installed in the NDK path as described in @ref building-cross-android, -build your project as below. The `CMAKE_FIND_ROOT_PATH` is unfortunately needed -for CMake to correctly find Android libraries, otherwise it falls back to -looking in native system locations. Adapt paths to your system, Android ABI and -version and NDK location as needed: +build your project as below. Adapt paths to your system, Android ABI and +version and NDK location as needed. + + + +@m_class{m-note m-warning} + +@par + Unfortunately, CMake before version 3.20 needs extra help with + `CMAKE_FIND_ROOT_PATH` and `CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` to + correctly find Android libraries, as shown below. Otherwise it falls back + to looking in native system locations. Again, adapt them to your system, + Android ABI and version and NDK location as needed. +@par + CMake 3.20 and newer [is now able to detect everything on its own](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5357) + and you don't need to supply these anymore. @m_class{m-console-wrap} @@ -84,7 +96,8 @@ cmake .. \ -DCMAKE_SYSTEM_VERSION=24 \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_STL_TYPE=c++_static \ - -DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ + -DCMAKE_FIND_ROOT_PATH=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot \ + -DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/aarch64-linux-android/24 \ -DCMAKE_BUILD_TYPE=Release cmake --build . @endcode @@ -409,7 +422,10 @@ After that, you can add the additional ABIs to the `abiFilters` list in your `build.gradle`. For example, building Magnum for 32-bit and 64-bit ARM with SDK version 24 -could look like this: +could look like this. The same note regarding CMake 3.20 applies here --- on +versions before, you need the `CMAKE_FIND_ROOT_PATH` and +`CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX` variables as well (and have them in sync +with the ABI and API version level), on 3.20 and newer you can omit them. @m_class{m-console-wrap} @@ -421,9 +437,9 @@ cmake .. \ -DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a \ -DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/platforms/android-24/arch-arm/usr \ - -DCMAKE_FIND_ROOT_PATH="platforms/android-24/arch-arm;/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ - -DMAGNUM_INCLUDE_INSTALL_PREFIX=/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr + -DCMAKE_INSTALL_PREFIX=/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \ + -DCMAKE_FIND_ROOT_PATH=/toolchains/llvm/prebuilt/linux-x86_64/sysroot \ + -DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/arm-linux-androideabi/24 cmake --build . --target install cd .. @@ -435,9 +451,9 @@ cmake .. \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_STL_TYPE=c++_static \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/platforms/android-24/arch-arm64/usr \ - -DCMAKE_FIND_ROOT_PATH="platforms/android-24/arch-arm64;/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ - -DMAGNUM_INCLUDE_INSTALL_PREFIX=/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr + -DCMAKE_INSTALL_PREFIX=/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \ + -DCMAKE_FIND_ROOT_PATH=/toolchains/llvm/prebuilt/linux-x86_64/sysroot \ + -DCMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX=/aarch64-linux-android/24 cmake --build . --target install @endcode diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake index 1747711e6..9a36cce28 100644 --- a/modules/FindCorrade.cmake +++ b/modules/FindCorrade.cmake @@ -11,9 +11,6 @@ # # Corrade_FOUND - Whether the base library was found # CORRADE_LIB_SUFFIX_MODULE - Path to CorradeLibSuffix.cmake module -# CORRADE_INCLUDE_INSTALL_PREFIX - Prefix where to put platform-independent -# include and other files, defaults to ``.``. If a relative path is used, -# it's relative to :variable:`CMAKE_INSTALL_PREFIX`. # # This command will try to find only the base library, not the optional # components, which are: @@ -618,8 +615,9 @@ find_package_handle_standard_args(Corrade REQUIRED_VARS # Finalize the finding process include(${CORRADE_USE_MODULE}) -# Installation dirs -set(CORRADE_INCLUDE_INSTALL_PREFIX "." - CACHE STRING "Prefix where to put platform-independent include and other files") +set(CORRADE_INCLUDE_INSTALL_DIR include/Corrade) -set(CORRADE_INCLUDE_INSTALL_DIR ${CORRADE_INCLUDE_INSTALL_PREFIX}/include/Corrade) +if(CORRADE_BUILD_DEPRECATED AND CORRADE_INCLUDE_INSTALL_PREFIX AND NOT CORRADE_INCLUDE_INSTALL_PREFIX STREQUAL ".") + message(DEPRECATION "CORRADE_INCLUDE_INSTALL_PREFIX is obsolete as its primary use was for old Android NDK versions. Please switch to the NDK r19+ layout instead of using this variable and recreate your build directory to get rid of this warning.") + set(CORRADE_INCLUDE_INSTALL_DIR ${CORRADE_INCLUDE_INSTALL_PREFIX}/${CORRADE_INCLUDE_INSTALL_DIR}) +endif() diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index a05edf03f..1c150aa05 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -13,9 +13,6 @@ # MAGNUM_DEPLOY_PREFIX - Prefix where to put final application # executables, defaults to ``.``. If a relative path is used, it's relative # to :variable:`CMAKE_INSTALL_PREFIX`. -# MAGNUM_INCLUDE_INSTALL_PREFIX - Prefix where to put platform-independent -# include and other files, defaults to ``.``. If a relative path is used, -# it's relative to :variable:`CMAKE_INSTALL_PREFIX`. # MAGNUM_PLUGINS_DEBUG_DIR - Base directory with dynamic plugins for # debug builds, defaults to magnum-d/ subdirectory of dir where Magnum # library was found @@ -1185,17 +1182,27 @@ endif() # Installation and deploy dirs set(MAGNUM_DEPLOY_PREFIX "." CACHE STRING "Prefix where to put final application executables") -set(MAGNUM_INCLUDE_INSTALL_PREFIX "." - CACHE STRING "Prefix where to put platform-independent include and other files") include(${CORRADE_LIB_SUFFIX_MODULE}) set(MAGNUM_BINARY_INSTALL_DIR bin) set(MAGNUM_LIBRARY_INSTALL_DIR lib${LIB_SUFFIX}) -set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/share/magnum) +set(MAGNUM_DATA_INSTALL_DIR share/magnum) +set(MAGNUM_INCLUDE_INSTALL_DIR include/Magnum) +set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR include/MagnumExternal) +set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR include/MagnumPlugins) +if(MAGNUM_BUILD_DEPRECATED AND MAGNUM_INCLUDE_INSTALL_PREFIX AND NOT MAGNUM_INCLUDE_INSTALL_PREFIX STREQUAL ".") + message(DEPRECATION "MAGNUM_INCLUDE_INSTALL_PREFIX is obsolete as its primary use was for old Android NDK versions. Please switch to the NDK r19+ layout instead of using this variable and recreate your build directory to get rid of this warning.") + set(MAGNUM_DATA_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_DATA_INSTALL_DIR}) + set(MAGNUM_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_INCLUDE_INSTALL_DIR}) + set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR}) + set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR}) +endif() + set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-d) 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) @@ -1222,9 +1229,6 @@ set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG 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) set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/audioimporters) -set(MAGNUM_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/Magnum) -set(MAGNUM_EXTERNAL_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/MagnumExternal) -set(MAGNUM_PLUGINS_INCLUDE_INSTALL_DIR ${MAGNUM_INCLUDE_INSTALL_PREFIX}/include/MagnumPlugins) # Get base plugin directory from main library location. This is *not* PATH, # because CMake always converts the path to an absolute location internally, diff --git a/package/archlinux/PKGBUILD-android-arm64 b/package/archlinux/PKGBUILD-android-arm64 index 65fb08c03..8697430be 100644 --- a/package/archlinux/PKGBUILD-android-arm64 +++ b/package/archlinux/PKGBUILD-android-arm64 @@ -7,7 +7,7 @@ arch=('any') url="https://magnum.graphics" license=('MIT') depends=('android-arm64-corrade') -makedepends=('cmake' 'ninja' 'android-ndk' 'corrade') +makedepends=('cmake>=3.20' 'ninja' 'android-ndk' 'corrade') options=('!strip' '!buildflags') _rootdir=$startdir/../../ @@ -22,17 +22,14 @@ build() { -DCMAKE_SYSTEM_VERSION=24 \ -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ -DCMAKE_ANDROID_STL_TYPE=c++_static \ - -DCMAKE_FIND_ROOT_PATH="/opt/android-ndk/platforms/android-24/arch-arm64;/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot" \ + -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \ -G Ninja - fi cd "$_rootdir/build-android-arm64" cmake .. \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/opt/android-ndk/platforms/android-24/arch-arm64/usr \ - -DMAGNUM_INCLUDE_INSTALL_PREFIX=/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr \ -DWITH_VK=ON \ -DWITH_ANYAUDIOIMPORTER=OFF \ -DWITH_ANYIMAGECONVERTER=ON \ From a7389cb9503ea4c3a39d39156e5db7226b4dd6a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 1 Apr 2021 10:09:07 +0200 Subject: [PATCH 109/161] Math: doc++ --- src/Magnum/Math/TypeTraits.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Math/TypeTraits.h b/src/Magnum/Math/TypeTraits.h index 1a4de8391..2a4ad7729 100644 --- a/src/Magnum/Math/TypeTraits.h +++ b/src/Magnum/Math/TypeTraits.h @@ -308,9 +308,9 @@ namespace Implementation { /** @brief Traits class for builtin arithmetic types -Traits classes are usable for detecting type features at compile time without -the need for repeated code such as method overloading or template -specialization for given types. All builtin arithmetic types have this class +Useful for detecting type features at compile time without the need for +repeated code such as method overloading, cascaded ifs or template +specializations for given types. All builtin arithmetic types have this class implemented. */ template struct TypeTraits: Implementation::TypeTraitsDefault { @@ -333,8 +333,8 @@ template struct TypeTraits: Implementation::TypeTraitsDefault { /** * @brief Type name * - * Returns a string representation of type name, such as `"UnsignedInt"` - * for @ref Magnum::UnsignedInt "UnsignedInt". + * Returns a string representation of type name, such as + * @cpp "UnsignedInt" @ce for @relativeref{Magnum,UnsignedInt}. */ constexpr static const char* name(); From b3fd0b379585a7b095fa0edbf01554bdc5ce48a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 1 Apr 2021 12:33:00 +0200 Subject: [PATCH 110/161] GL: adapt OpenGLTester to changes in TestSuite. --- src/Magnum/GL/OpenGLTester.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Magnum/GL/OpenGLTester.cpp b/src/Magnum/GL/OpenGLTester.cpp index e14b2ecc3..b872115c5 100644 --- a/src/Magnum/GL/OpenGLTester.cpp +++ b/src/Magnum/GL/OpenGLTester.cpp @@ -44,17 +44,25 @@ void OpenGLTester::gpuTimeBenchmarkBegin() { /* Initialize, if not already; check for extension presence and skip if not available. This function is always called from inside CORRADE_BENCHMARK, - which does the test case registration on a proper function. */ + which does the test case registration on a proper function, thus we + don't need to use the CORRADE_SKIP() macro, which avoids some + unnecessary work. */ if(!_gpuTimeQuery.id()) { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - skip("GL_ARB_timer_query is not supported"); + skip([](Debug&& debug) { + debug << "GL_ARB_timer_query is not supported"; + }); #elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - skip("GL_EXT_disjoint_timer_query_webgl2 is not supported"); + skip([](Debug&& debug) { + debug << "GL_EXT_disjoint_timer_query_webgl2 is not supported"; + }); #else if(!Context::current().isExtensionSupported()) - skip("GL_EXT_disjoint_timer_query is not supported"); + skip([](Debug&& debug) { + debug << "GL_EXT_disjoint_timer_query is not supported"; + }); #endif _gpuTimeQuery = TimeQuery{TimeQuery::Target::TimeElapsed}; } From 65a935cedc059bab49172b9a198e3ccc6b346bdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 1 Apr 2021 12:31:19 +0200 Subject: [PATCH 111/161] Test: adapt to changes in CORRADE_SKIP(). Chose to update the tests instead of adding a compatibility DebugStl.h include to Tester.h, which would have a significant impact on compile times. --- src/Magnum/Audio/Test/BufferALTest.cpp | 10 +- src/Magnum/Audio/Test/ContextALTest.cpp | 2 +- .../DebugTools/Test/BufferDataGLTest.cpp | 8 +- .../DebugTools/Test/FrameProfilerGLTest.cpp | 12 +- .../DebugTools/Test/TextureImageGLTest.cpp | 2 +- src/Magnum/GL/Test/AbstractQueryGLTest.cpp | 6 +- .../GL/Test/AbstractShaderProgramGLTest.cpp | 22 +- src/Magnum/GL/Test/AbstractTextureGLTest.cpp | 34 +-- src/Magnum/GL/Test/BufferGLTest.cpp | 14 +- src/Magnum/GL/Test/BufferTextureGLTest.cpp | 48 ++-- src/Magnum/GL/Test/ContextGLTest.cpp | 18 +- .../GL/Test/CubeMapTextureArrayGLTest.cpp | 176 +++++++------- src/Magnum/GL/Test/CubeMapTextureGLTest.cpp | 150 ++++++------ src/Magnum/GL/Test/DebugOutputGLTest.cpp | 8 +- src/Magnum/GL/Test/FramebufferGLTest.cpp | 160 ++++++------- src/Magnum/GL/Test/MeshGLTest.cpp | 124 +++++----- .../GL/Test/MultisampleTextureGLTest.cpp | 48 ++-- .../GL/Test/PipelineStatisticsQueryGLTest.cpp | 4 +- src/Magnum/GL/Test/PixelStorageGLTest.cpp | 12 +- src/Magnum/GL/Test/PrimitiveQueryGLTest.cpp | 12 +- src/Magnum/GL/Test/RectangleTextureGLTest.cpp | 56 ++--- src/Magnum/GL/Test/RenderbufferGLTest.cpp | 12 +- src/Magnum/GL/Test/RendererGLTest.cpp | 12 +- src/Magnum/GL/Test/SampleQueryGLTest.cpp | 6 +- src/Magnum/GL/Test/TextureArrayGLTest.cpp | 196 ++++++++-------- src/Magnum/GL/Test/TextureGLTest.cpp | 218 +++++++++--------- src/Magnum/GL/Test/TimeQueryGLTest.cpp | 18 +- .../GL/Test/TransformFeedbackGLTest.cpp | 22 +- src/Magnum/MeshTools/Test/CompileGLTest.cpp | 8 +- src/Magnum/Shaders/Test/FlatGLTest.cpp | 14 +- .../Shaders/Test/MeshVisualizerGLTest.cpp | 68 +++--- src/Magnum/Shaders/Test/PhongGLTest.cpp | 8 +- src/Magnum/Text/Test/RendererGLTest.cpp | 2 +- .../TextureTools/Test/DistanceFieldGLTest.cpp | 2 +- 34 files changed, 756 insertions(+), 756 deletions(-) diff --git a/src/Magnum/Audio/Test/BufferALTest.cpp b/src/Magnum/Audio/Test/BufferALTest.cpp index c49ca564e..94cfd7015 100644 --- a/src/Magnum/Audio/Test/BufferALTest.cpp +++ b/src/Magnum/Audio/Test/BufferALTest.cpp @@ -84,7 +84,7 @@ void BufferALTest::properties() { void BufferALTest::loopPoints() { if(!_context.isExtensionSupported()) - CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported."); Buffer buf; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; @@ -95,7 +95,7 @@ void BufferALTest::loopPoints() { void BufferALTest::setLoopPoints() { if(!_context.isExtensionSupported()) - CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported."); Buffer buf; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; @@ -106,7 +106,7 @@ void BufferALTest::setLoopPoints() { void BufferALTest::setLoopSince() { if(!_context.isExtensionSupported()) - CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported."); Buffer buf; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; @@ -117,7 +117,7 @@ void BufferALTest::setLoopSince() { void BufferALTest::setLoopUntil() { if(!_context.isExtensionSupported()) - CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported."); Buffer buf; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; @@ -128,7 +128,7 @@ void BufferALTest::setLoopUntil() { void BufferALTest::resetLoopPoints() { if(!_context.isExtensionSupported()) - CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::AL::SOFT::loop_points::string() << "is not supported."); Buffer buf; constexpr char data[] { 25, 17, 24, 122, 67, 24, 48, 96 }; diff --git a/src/Magnum/Audio/Test/ContextALTest.cpp b/src/Magnum/Audio/Test/ContextALTest.cpp index ec7abea68..9c8244356 100644 --- a/src/Magnum/Audio/Test/ContextALTest.cpp +++ b/src/Magnum/Audio/Test/ContextALTest.cpp @@ -131,7 +131,7 @@ void ContextALTest::isExtensionUnsupported() { Context context; if(context.isExtensionSupported()) - CORRADE_SKIP("Extension" + std::string{Extensions::ALC::SOFTX::HRTF::string()} + " is supported, can't test."); + CORRADE_SKIP("Extension" << Extensions::ALC::SOFTX::HRTF::string() << "is supported, can't test."); CORRADE_VERIFY(!context.isExtensionSupported()); CORRADE_VERIFY(!context.isExtensionDisabled()); diff --git a/src/Magnum/DebugTools/Test/BufferDataGLTest.cpp b/src/Magnum/DebugTools/Test/BufferDataGLTest.cpp index 51e8f4750..fd1c21502 100644 --- a/src/Magnum/DebugTools/Test/BufferDataGLTest.cpp +++ b/src/Magnum/DebugTools/Test/BufferDataGLTest.cpp @@ -49,10 +49,10 @@ constexpr Int Data[] = {2, 7, 5, 13, 25}; void BufferDataGLTest::data() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() << "is not supported."); #endif GL::Buffer buffer; @@ -66,10 +66,10 @@ void BufferDataGLTest::data() { void BufferDataGLTest::subData() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() << "is not supported."); #endif GL::Buffer buffer; diff --git a/src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp b/src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp index b1b4304a1..534c1006f 100644 --- a/src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp +++ b/src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp @@ -81,19 +81,19 @@ void FrameProfilerGLTest::test() { if(data.values & GLFrameProfiler::Value::GpuDuration) { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::timer_query::string() + std::string(" is not available")); + CORRADE_SKIP(GL::Extensions::ARB::timer_query::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query_webgl2::string() + std::string(" is not available")); + CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query_webgl2::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available")); + CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query::string() << "is not supported."); #endif } #ifndef MAGNUM_TARGET_GLES if((data.values & GLFrameProfiler::Value::VertexFetchRatio) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() + std::string(" is not available")); + CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported."); #endif /* Bind some FB to avoid errors on contexts w/o default FB */ @@ -188,7 +188,7 @@ void FrameProfilerGLTest::test() { #ifndef MAGNUM_TARGET_GLES void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() { if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() + std::string(" is not available")); + CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported."); GLFrameProfiler profiler{GLFrameProfiler::Value::VertexFetchRatio, 4}; @@ -214,7 +214,7 @@ void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() { void FrameProfilerGLTest::primitiveClipRatioDivisionByZero() { if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() + std::string(" is not available")); + CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported."); GLFrameProfiler profiler{GLFrameProfiler::Value::PrimitiveClipRatio, 4}; diff --git a/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp b/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp index 8cb00942d..25c90a722 100644 --- a/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp +++ b/src/Magnum/DebugTools/Test/TextureImageGLTest.cpp @@ -208,7 +208,7 @@ constexpr UnsignedInt Data2DUInt[] = { 0xcafebabe, void TextureImageGLTest::subImage2DUInt() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::texture_integer::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::texture_integer::string() << "is not supported."); #endif GL::Texture2D texture; diff --git a/src/Magnum/GL/Test/AbstractQueryGLTest.cpp b/src/Magnum/GL/Test/AbstractQueryGLTest.cpp index 1a5db3ef2..5b9ed7750 100644 --- a/src/Magnum/GL/Test/AbstractQueryGLTest.cpp +++ b/src/Magnum/GL/Test/AbstractQueryGLTest.cpp @@ -56,7 +56,7 @@ AbstractQueryGLTest::AbstractQueryGLTest() { void AbstractQueryGLTest::construct() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() << "is not supported."); #endif { @@ -76,7 +76,7 @@ void AbstractQueryGLTest::construct() { void AbstractQueryGLTest::constructMove() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES @@ -114,7 +114,7 @@ void AbstractQueryGLTest::constructMove() { void AbstractQueryGLTest::label() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() << "is not supported."); #endif /* No-Op version is tested in AbstractObjectGLTest */ diff --git a/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp b/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp index 78aca83b7..d8490ec7f 100644 --- a/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp +++ b/src/Magnum/GL/Test/AbstractShaderProgramGLTest.cpp @@ -269,7 +269,7 @@ void AbstractShaderProgramGLTest::create() { void AbstractShaderProgramGLTest::createMultipleOutputs() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); Utility::Resource rs("AbstractShaderProgramGLTest"); @@ -326,9 +326,9 @@ void AbstractShaderProgramGLTest::createMultipleOutputs() { #ifndef MAGNUM_TARGET_GLES void AbstractShaderProgramGLTest::createMultipleOutputsIndexed() { if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::blend_func_extended::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::blend_func_extended::string() << "is not supported."); Utility::Resource rs("AbstractShaderProgramGLTest"); @@ -590,7 +590,7 @@ MyDoubleShader::MyDoubleShader() { void AbstractShaderProgramGLTest::uniformDouble() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::gpu_shader_fp64::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::ARB::gpu_shader_fp64::string() << "is not supported."); MyDoubleShader shader; @@ -603,7 +603,7 @@ void AbstractShaderProgramGLTest::uniformDouble() { void AbstractShaderProgramGLTest::uniformDoubleVector() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::gpu_shader_fp64::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::ARB::gpu_shader_fp64::string() << "is not supported."); MyDoubleShader shader; @@ -616,7 +616,7 @@ void AbstractShaderProgramGLTest::uniformDoubleVector() { void AbstractShaderProgramGLTest::uniformDoubleMatrix() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::gpu_shader_fp64::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::ARB::gpu_shader_fp64::string() << "is not supported."); MyDoubleShader shader; @@ -629,7 +629,7 @@ void AbstractShaderProgramGLTest::uniformDoubleMatrix() { void AbstractShaderProgramGLTest::uniformDoubleArray() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::gpu_shader_fp64::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::ARB::gpu_shader_fp64::string() << "is not supported."); MyDoubleShader shader; @@ -654,7 +654,7 @@ void AbstractShaderProgramGLTest::uniformDoubleArray() { void AbstractShaderProgramGLTest::createUniformBlocks() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif Utility::Resource rs("AbstractShaderProgramGLTest"); @@ -711,7 +711,7 @@ void AbstractShaderProgramGLTest::createUniformBlocks() { void AbstractShaderProgramGLTest::uniformBlockIndexNotFound() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif MyPublicShader program; @@ -790,7 +790,7 @@ UniformBlockShader::UniformBlockShader() { void AbstractShaderProgramGLTest::uniformBlock() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif UniformBlockShader shader; @@ -807,7 +807,7 @@ void AbstractShaderProgramGLTest::uniformBlock() { void AbstractShaderProgramGLTest::compute() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compute_shader::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compute_shader::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); diff --git a/src/Magnum/GL/Test/AbstractTextureGLTest.cpp b/src/Magnum/GL/Test/AbstractTextureGLTest.cpp index 50c880a5c..ef3e5ccf4 100644 --- a/src/Magnum/GL/Test/AbstractTextureGLTest.cpp +++ b/src/Magnum/GL/Test/AbstractTextureGLTest.cpp @@ -186,7 +186,7 @@ void AbstractTextureGLTest::subImageQueryViewBadSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2}); @@ -208,7 +208,7 @@ void AbstractTextureGLTest::compressedImageQueryViewNullptr() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -229,7 +229,7 @@ void AbstractTextureGLTest::compressedImageQueryViewBadSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -251,7 +251,7 @@ void AbstractTextureGLTest::compressedImageQueryViewBadDataSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -273,7 +273,7 @@ void AbstractTextureGLTest::compressedImageQueryViewBadFormat() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -295,11 +295,11 @@ void AbstractTextureGLTest::compressedSubImageQueryViewNullptr() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -320,11 +320,11 @@ void AbstractTextureGLTest::compressedSubImageQueryViewBadSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -346,11 +346,11 @@ void AbstractTextureGLTest::compressedSubImageQueryViewBadDataSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -372,11 +372,11 @@ void AbstractTextureGLTest::compressedSubImageQueryViewBadFormat() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); diff --git a/src/Magnum/GL/Test/BufferGLTest.cpp b/src/Magnum/GL/Test/BufferGLTest.cpp index 1a5c938b6..873ce69b7 100644 --- a/src/Magnum/GL/Test/BufferGLTest.cpp +++ b/src/Magnum/GL/Test/BufferGLTest.cpp @@ -207,7 +207,7 @@ void BufferGLTest::label() { void BufferGLTest::bindBase() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::uniform_buffer_object::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif Buffer buffer; @@ -231,7 +231,7 @@ void BufferGLTest::bindBase() { void BufferGLTest::bindRange() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::uniform_buffer_object::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::ARB::uniform_buffer_object::string() << "is not supported."); #endif /* Check that we have correct offset alignment */ @@ -329,7 +329,7 @@ void BufferGLTest::data() { void BufferGLTest::map() { #ifdef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::mapbuffer::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::OES::mapbuffer::string() << "is not supported."); #endif Buffer buffer; @@ -365,10 +365,10 @@ void BufferGLTest::map() { void BufferGLTest::mapRange() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::ARB::map_buffer_range::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::EXT::map_buffer_range::string() << "is not supported."); #endif constexpr char data[] = {2, 7, 5, 13, 25}; @@ -397,10 +397,10 @@ void BufferGLTest::mapRange() { void BufferGLTest::mapRangeExplicitFlush() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::ARB::map_buffer_range::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::EXT::map_buffer_range::string() << "is not supported."); #endif constexpr char data[] = {2, 7, 5, 13, 25}; diff --git a/src/Magnum/GL/Test/BufferTextureGLTest.cpp b/src/Magnum/GL/Test/BufferTextureGLTest.cpp index 56b8c7e23..cd7ba20d3 100644 --- a/src/Magnum/GL/Test/BufferTextureGLTest.cpp +++ b/src/Magnum/GL/Test/BufferTextureGLTest.cpp @@ -95,10 +95,10 @@ BufferTextureGLTest::BufferTextureGLTest() { void BufferTextureGLTest::construct() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_buffer::string() << "is not supported."); #endif { @@ -123,10 +123,10 @@ void BufferTextureGLTest::constructMove() { void BufferTextureGLTest::wrap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_buffer::string() << "is not supported."); #endif GLuint id; @@ -146,10 +146,10 @@ void BufferTextureGLTest::wrap() { void BufferTextureGLTest::bind() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_buffer::string() << "is not supported."); #endif BufferTexture texture; @@ -173,12 +173,12 @@ void BufferTextureGLTest::bind() { void BufferTextureGLTest::bindImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_buffer::string() << "is not supported."); if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); #endif @@ -210,10 +210,10 @@ void BufferTextureGLTest::bindImage() { void BufferTextureGLTest::setBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_buffer::string() << "is not supported."); #endif BufferTexture texture; @@ -240,10 +240,10 @@ void BufferTextureGLTest::setBuffer() { void BufferTextureGLTest::setBufferEmptyFirst() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_buffer::string() << "is not supported."); #endif BufferTexture texture; @@ -276,12 +276,12 @@ void BufferTextureGLTest::setBufferEmptyFirst() { void BufferTextureGLTest::setBufferOffset() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_range::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_range::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_buffer::string() << "is not supported."); #endif /* Check that we have correct offset alignment */ @@ -314,10 +314,10 @@ void BufferTextureGLTest::setBufferOffset() { void BufferTextureGLTest::resetBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_buffer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_buffer::string() << "is not supported."); #endif BufferTexture texture; @@ -351,7 +351,7 @@ void BufferTextureGLTest::resetBuffer() { #if defined(CORRADE_TARGET_APPLE) && !defined(CORRADE_TARGET_IOS) void BufferTextureGLTest::appleSetBufferSubData() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); BufferTexture texture; Buffer buffer{Buffer::TargetHint::Texture}; @@ -373,7 +373,7 @@ void BufferTextureGLTest::appleSetBufferSubData() { void BufferTextureGLTest::appleSetUnrelatedBufferData() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); BufferTexture texture; Buffer buffer{Buffer::TargetHint::Texture}; @@ -396,7 +396,7 @@ void BufferTextureGLTest::appleSetUnrelatedBufferData() { void BufferTextureGLTest::appleSetBufferQueryData() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); BufferTexture texture; Buffer buffer{Buffer::TargetHint::Texture}; @@ -419,7 +419,7 @@ void BufferTextureGLTest::appleSetBufferQueryData() { void BufferTextureGLTest::appleSetBufferMap() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); BufferTexture texture; Buffer buffer{Buffer::TargetHint::Texture}; @@ -445,7 +445,7 @@ void BufferTextureGLTest::appleSetBufferMap() { void BufferTextureGLTest::appleSetBufferMapRange() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); BufferTexture texture; Buffer buffer{Buffer::TargetHint::Texture}; @@ -476,7 +476,7 @@ void BufferTextureGLTest::appleSetBufferMapRange() { void BufferTextureGLTest::appleBindUnrelatedTextureInBetween() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_buffer_object::string() << "is not supported."); BufferTexture texture; Buffer buffer{Buffer::TargetHint::Texture}; diff --git a/src/Magnum/GL/Test/ContextGLTest.cpp b/src/Magnum/GL/Test/ContextGLTest.cpp index 5dfd5edd5..7b6e878b4 100644 --- a/src/Magnum/GL/Test/ContextGLTest.cpp +++ b/src/Magnum/GL/Test/ContextGLTest.cpp @@ -260,9 +260,9 @@ void ContextGLTest::constructConfiguration() { CORRADE_VERIFY(Context::hasCurrent()); if(data.needsExtensionPresent && !Context::current().isExtensionSupported(*data.needsExtensionPresent)) - CORRADE_SKIP(data.needsExtensionPresent->string() + std::string{" is not supported, skippping"}); + CORRADE_SKIP(data.needsExtensionPresent->string() << "is not supported."); if(data.needsExtensionMissing && Context::current().isExtensionSupported(*data.needsExtensionMissing)) - CORRADE_SKIP(data.needsExtensionMissing->string() + std::string{" is supported, skippping"}); + CORRADE_SKIP(data.needsExtensionMissing->string() << "is supported."); std::ostringstream out; { @@ -297,7 +297,7 @@ void ContextGLTest::constructMove() { CORRADE_VERIFY(Context::hasCurrent()); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_filter_anisotropic::string() + std::string{" is not supported, skipping"}); + CORRADE_SKIP(Extensions::EXT::texture_filter_anisotropic::string() << "is not supported."); Context* current = &Context::current(); Context::makeCurrent(nullptr); @@ -457,7 +457,7 @@ void ContextGLTest::isVersionSupported() { #ifndef MAGNUM_TARGET_GLES void ContextGLTest::isVersionSupportedES() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::ES2_compatibility::string() + std::string(" extension should not be supported, can't test")); + CORRADE_SKIP(Extensions::ARB::ES2_compatibility::string() << "should not be supported, can't test."); /* No assertions should be fired */ CORRADE_VERIFY(Context::current().isVersionSupported(Version::GLES200)); @@ -475,13 +475,13 @@ void ContextGLTest::supportedVersion() { void ContextGLTest::isExtensionSupported() { #ifndef MAGNUM_TARGET_GLES if(Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::GREMEDY::string_marker::string() + std::string(" extension should not be supported, can't test")); + CORRADE_SKIP(Extensions::GREMEDY::string_marker::string() << "should not be supported, can't test."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_filter_anisotropic::string() + std::string(" extension should be supported, can't test")); + CORRADE_SKIP(Extensions::EXT::texture_filter_anisotropic::string() << "should be supported, can't test."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::explicit_attrib_location::string() + std::string(" extension should be supported, can't test")); + CORRADE_SKIP(Extensions::ARB::explicit_attrib_location::string() << "should be supported, can't test."); /* Test that we have proper extension list parser */ Containers::Array extensions = Context::current().extensionStrings(); @@ -501,10 +501,10 @@ void ContextGLTest::isExtensionSupported() { void ContextGLTest::isExtensionDisabled() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() + std::string(" extension should be supported, can't test")); + CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() << "should be supported, can't test."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::explicit_attrib_location::string() + std::string(" extension should be supported, can't test")); + CORRADE_SKIP(Extensions::ARB::explicit_attrib_location::string() << "should be supported, can't test."); /* This is not disabled anywhere */ CORRADE_VERIFY(!Context::current().isExtensionDisabled()); diff --git a/src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp b/src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp index 3e798d88a..5344f2184 100644 --- a/src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp +++ b/src/Magnum/GL/Test/CubeMapTextureArrayGLTest.cpp @@ -329,10 +329,10 @@ CubeMapTextureArrayGLTest::CubeMapTextureArrayGLTest() { void CubeMapTextureArrayGLTest::construct() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif { @@ -357,10 +357,10 @@ void CubeMapTextureArrayGLTest::constructMove() { void CubeMapTextureArrayGLTest::wrap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif GLuint id; @@ -380,10 +380,10 @@ void CubeMapTextureArrayGLTest::wrap() { void CubeMapTextureArrayGLTest::bind() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -407,12 +407,12 @@ void CubeMapTextureArrayGLTest::bind() { void CubeMapTextureArrayGLTest::bindImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); #endif @@ -447,10 +447,10 @@ template void CubeMapTextureArrayGLTest::sampling() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -479,13 +479,13 @@ template void CubeMapTextureArrayGLTest::sampling() { void CubeMapTextureArrayGLTest::samplingSrgbDecode() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() << "is not supported."); CubeMapTextureArray texture; texture.setSrgbDecode(false); @@ -496,14 +496,14 @@ void CubeMapTextureArrayGLTest::samplingSrgbDecode() { void CubeMapTextureArrayGLTest::samplingBorderInteger() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_integer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_integer::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() << "is not supported."); #endif CubeMapTextureArray a; @@ -519,12 +519,12 @@ void CubeMapTextureArrayGLTest::samplingBorderInteger() { void CubeMapTextureArrayGLTest::samplingSwizzle() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -536,12 +536,12 @@ void CubeMapTextureArrayGLTest::samplingSwizzle() { void CubeMapTextureArrayGLTest::samplingDepthStencilMode() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -553,9 +553,9 @@ void CubeMapTextureArrayGLTest::samplingDepthStencilMode() { #ifdef MAGNUM_TARGET_GLES void CubeMapTextureArrayGLTest::samplingBorder() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() << "is not supported."); CubeMapTextureArray texture; texture.setWrapping(SamplerWrapping::ClampToBorder) @@ -568,10 +568,10 @@ void CubeMapTextureArrayGLTest::samplingBorder() { void CubeMapTextureArrayGLTest::storage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -594,10 +594,10 @@ void CubeMapTextureArrayGLTest::image() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -626,10 +626,10 @@ void CubeMapTextureArrayGLTest::imageBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -661,7 +661,7 @@ void CubeMapTextureArrayGLTest::imageQueryView() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); CubeMapTextureArray texture; texture.setImage(0, TextureFormat::RGBA8, ImageView3D{ @@ -689,22 +689,22 @@ void CubeMapTextureArrayGLTest::compressedImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -734,22 +734,22 @@ void CubeMapTextureArrayGLTest::compressedImageBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -782,12 +782,12 @@ void CubeMapTextureArrayGLTest::compressedImageQueryView() { setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CubeMapTextureArray texture; texture.setCompressedImage(0, CompressedImageView3D{ @@ -852,10 +852,10 @@ void CubeMapTextureArrayGLTest::subImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -885,10 +885,10 @@ void CubeMapTextureArrayGLTest::subImageBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -921,9 +921,9 @@ void CubeMapTextureArrayGLTest::subImageQuery() { setTestCaseDescription(SubPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); CubeMapTextureArray texture; texture.setStorage(1, TextureFormat::RGBA8, {4, 4, 6}) @@ -947,9 +947,9 @@ void CubeMapTextureArrayGLTest::subImageQueryView() { setTestCaseDescription(SubPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); CubeMapTextureArray texture; texture.setStorage(1, TextureFormat::RGBA8, {4, 4, 6}) @@ -973,9 +973,9 @@ void CubeMapTextureArrayGLTest::subImageQueryBuffer() { setTestCaseDescription(SubPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); CubeMapTextureArray texture; texture.setStorage(1, TextureFormat::RGBA8, {4, 4, 6}) @@ -1068,22 +1068,22 @@ void CubeMapTextureArrayGLTest::compressedSubImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -1121,22 +1121,22 @@ void CubeMapTextureArrayGLTest::compressedSubImageBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -1170,15 +1170,15 @@ void CubeMapTextureArrayGLTest::compressedSubImageQuery() { setTestCaseDescription(CompressedSubPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedSubPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedSubPixelStorageData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); CubeMapTextureArray texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 12, 6}) @@ -1200,15 +1200,15 @@ void CubeMapTextureArrayGLTest::compressedSubImageQueryView() { setTestCaseDescription(CompressedSubPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedSubPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedSubPixelStorageData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); CubeMapTextureArray texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 12, 6}) @@ -1232,15 +1232,15 @@ void CubeMapTextureArrayGLTest::compressedSubImageQueryBuffer() { setTestCaseDescription(CompressedSubPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedSubPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedSubPixelStorageData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); CubeMapTextureArray texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 12, 6}) @@ -1263,12 +1263,12 @@ void CubeMapTextureArrayGLTest::compressedSubImageQueryBuffer() { void CubeMapTextureArrayGLTest::generateMipmap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -1295,10 +1295,10 @@ void CubeMapTextureArrayGLTest::generateMipmap() { void CubeMapTextureArrayGLTest::invalidateImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; @@ -1311,10 +1311,10 @@ void CubeMapTextureArrayGLTest::invalidateImage() { void CubeMapTextureArrayGLTest::invalidateSubImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray texture; diff --git a/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp b/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp index 35c57e9d1..4d46d284b 100644 --- a/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp @@ -490,7 +490,7 @@ void CubeMapTextureGLTest::bind() { void CubeMapTextureGLTest::bindImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -557,10 +557,10 @@ template void CubeMapTextureGLTest::sampling() { void CubeMapTextureGLTest::samplingSrgbDecode() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::sRGB::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::sRGB::string() << "is not supported."); #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() << "is not supported."); CubeMapTexture texture; texture.setSrgbDecode(false); @@ -573,7 +573,7 @@ void CubeMapTextureGLTest::samplingSrgbDecode() { void CubeMapTextureGLTest::samplingSwizzle() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() << "is not supported."); #endif CubeMapTexture texture; @@ -586,7 +586,7 @@ void CubeMapTextureGLTest::samplingSwizzle() { #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void CubeMapTextureGLTest::samplingMaxLevel() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::APPLE::texture_max_level::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::APPLE::texture_max_level::string() << "is not supported."); CubeMapTexture texture; texture.setMaxLevel(750); @@ -597,7 +597,7 @@ void CubeMapTextureGLTest::samplingMaxLevel() { void CubeMapTextureGLTest::samplingCompare() { if(!Context::current().isExtensionSupported() || !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::NV::shadow_samplers_cube::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::NV::shadow_samplers_cube::string() << "is not supported."); CubeMapTexture texture; texture.setCompareMode(SamplerCompareMode::CompareRefToTexture) @@ -611,10 +611,10 @@ void CubeMapTextureGLTest::samplingCompare() { void CubeMapTextureGLTest::samplingBorderInteger() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_integer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_integer::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() << "is not supported."); #endif CubeMapTexture a; @@ -630,7 +630,7 @@ void CubeMapTextureGLTest::samplingBorderInteger() { void CubeMapTextureGLTest::samplingDepthStencilMode() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 not supported."); @@ -695,7 +695,7 @@ void CubeMapTextureGLTest::storage() { #ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_WEBGL if(PixelStorageData[testCaseInstanceId()].storage != PixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() << "is not supported."); #else if(PixelStorageData[testCaseInstanceId()].storage != PixelStorage{}) CORRADE_SKIP("Image unpack is not supported in WebGL 1."); @@ -773,7 +773,7 @@ void CubeMapTextureGLTest::image() { #ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_WEBGL if(PixelStorageData[testCaseInstanceId()].storage != PixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() << "is not supported."); #else if(PixelStorageData[testCaseInstanceId()].storage != PixelStorage{}) CORRADE_SKIP("Image unpack is not supported in WebGL 1."); @@ -964,7 +964,7 @@ void CubeMapTextureGLTest::subImage() { #ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_WEBGL if(PixelStorageData[testCaseInstanceId()].storage != PixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() << "is not supported."); #else if(PixelStorageData[testCaseInstanceId()].storage != PixelStorage{}) CORRADE_SKIP("Image unpack is not supported in WebGL 1."); @@ -1054,7 +1054,7 @@ void CubeMapTextureGLTest::subImageQuery() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1078,7 +1078,7 @@ void CubeMapTextureGLTest::subImageQueryView() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1103,7 +1103,7 @@ void CubeMapTextureGLTest::subImageQueryBuffer() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1130,18 +1130,18 @@ void CubeMapTextureGLTest::compressedImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif const CompressedImageView2D view{ @@ -1179,18 +1179,18 @@ void CubeMapTextureGLTest::compressedImageBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif CompressedBufferImage2D buffer{ @@ -1231,10 +1231,10 @@ void CubeMapTextureGLTest::compressedImageQueryView() { setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); const CompressedImageView2D view{ CompressedPixelStorageData[testCaseInstanceId()].storage, @@ -1265,7 +1265,7 @@ void CubeMapTextureGLTest::compressedImageQueryViewNullptr() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -1286,7 +1286,7 @@ void CubeMapTextureGLTest::compressedImageQueryViewBadSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -1308,7 +1308,7 @@ void CubeMapTextureGLTest::compressedImageQueryViewBadDataSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -1330,7 +1330,7 @@ void CubeMapTextureGLTest::compressedImageQueryViewBadFormat() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -1353,25 +1353,25 @@ void CubeMapTextureGLTest::immutableCompressedImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_storage::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_storage::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif /* Testing that GL_TEXTURE_COMPRESSED_IMAGE_SIZE is consistent and returns @@ -1446,18 +1446,18 @@ void CubeMapTextureGLTest::compressedSubImage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif CubeMapTexture texture; @@ -1506,18 +1506,18 @@ void CubeMapTextureGLTest::compressedSubImageBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif CubeMapTexture texture; @@ -1563,13 +1563,13 @@ void CubeMapTextureGLTest::compressedSubImageQuery() { setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12}) @@ -1591,13 +1591,13 @@ void CubeMapTextureGLTest::compressedSubImageQueryView() { setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12}) @@ -1623,7 +1623,7 @@ void CubeMapTextureGLTest::compressedSubImageQueryViewNullptr() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12}); @@ -1644,7 +1644,7 @@ void CubeMapTextureGLTest::compressedSubImageQueryViewBadSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12}); @@ -1666,7 +1666,7 @@ void CubeMapTextureGLTest::compressedSubImageQueryViewBadDataSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12}); @@ -1688,7 +1688,7 @@ void CubeMapTextureGLTest::compressedSubImageQueryViewBadFormat() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12}); @@ -1708,13 +1708,13 @@ void CubeMapTextureGLTest::compressedSubImageQueryBuffer() { setTestCaseDescription(CompressedPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{12}) @@ -1740,7 +1740,7 @@ void CubeMapTextureGLTest::fullImageQuery() { setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2, 2}) @@ -1769,7 +1769,7 @@ void CubeMapTextureGLTest::fullImageQueryView() { setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2, 2}) @@ -1838,7 +1838,7 @@ void CubeMapTextureGLTest::fullImageQueryBuffer() { setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2}) @@ -1869,11 +1869,11 @@ void CubeMapTextureGLTest::compressedFullImageQuery() { setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}) @@ -1919,11 +1919,11 @@ void CubeMapTextureGLTest::compressedFullImageQueryView() { setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}) @@ -1973,7 +1973,7 @@ void CubeMapTextureGLTest::compressedFullImageQueryViewNullptr() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -1994,7 +1994,7 @@ void CubeMapTextureGLTest::compressedFullImageQueryViewBadSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -2016,7 +2016,7 @@ void CubeMapTextureGLTest::compressedFullImageQueryViewBadDataSize() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -2038,7 +2038,7 @@ void CubeMapTextureGLTest::compressedFullImageQueryViewBadFormat() { #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}); @@ -2058,11 +2058,11 @@ void CubeMapTextureGLTest::compressedFullImageQueryBuffer() { setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}) diff --git a/src/Magnum/GL/Test/DebugOutputGLTest.cpp b/src/Magnum/GL/Test/DebugOutputGLTest.cpp index 79d0ab1e8..8e7f50b15 100644 --- a/src/Magnum/GL/Test/DebugOutputGLTest.cpp +++ b/src/Magnum/GL/Test/DebugOutputGLTest.cpp @@ -71,7 +71,7 @@ DebugOutputGLTest::DebugOutputGLTest() { void DebugOutputGLTest::setCallbackDefault() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::KHR::debug::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::KHR::debug::string() << "is not supported."); DebugOutput::setDefaultCallback(); @@ -102,7 +102,7 @@ void DebugOutputGLTest::teardown() { void DebugOutputGLTest::setEnabled() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::KHR::debug::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::KHR::debug::string() << "is not supported."); /* Try at least some combinations. Calling a less-specific version will reset the more-specific setting from earlier. */ @@ -142,7 +142,7 @@ void DebugOutputGLTest::messageNoOp() { void DebugOutputGLTest::message() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::KHR::debug::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::KHR::debug::string() << "is not supported."); /* Need to be careful, because the test runner is using debug output too */ DebugMessage::insert(DebugMessage::Source::Application, DebugMessage::Type::Marker, @@ -185,7 +185,7 @@ void DebugOutputGLTest::groupNoOp() { void DebugOutputGLTest::group() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::KHR::debug::string() + std::string(" is not supported")); + CORRADE_SKIP(Extensions::KHR::debug::string() << "is not supported."); /* Need to be careful, because the test runner is using debug output too */ { diff --git a/src/Magnum/GL/Test/FramebufferGLTest.cpp b/src/Magnum/GL/Test/FramebufferGLTest.cpp index 0df578156..d4dfddb58 100644 --- a/src/Magnum/GL/Test/FramebufferGLTest.cpp +++ b/src/Magnum/GL/Test/FramebufferGLTest.cpp @@ -326,7 +326,7 @@ FramebufferGLTest::FramebufferGLTest() { void FramebufferGLTest::construct() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif { @@ -343,7 +343,7 @@ void FramebufferGLTest::construct() { void FramebufferGLTest::constructMove() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Framebuffer a({{32, 16}, {128, 256}}); @@ -375,7 +375,7 @@ void FramebufferGLTest::constructMove() { void FramebufferGLTest::wrap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif GLuint id; @@ -396,7 +396,7 @@ void FramebufferGLTest::wrap() { void FramebufferGLTest::label() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif /* No-Op version is tested in AbstractObjectGLTest */ @@ -419,7 +419,7 @@ void FramebufferGLTest::label() { void FramebufferGLTest::attachRenderbuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -471,7 +471,7 @@ void FramebufferGLTest::attachRenderbuffer() { void FramebufferGLTest::attachRenderbufferMultisample() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) @@ -510,7 +510,7 @@ void FramebufferGLTest::attachRenderbufferMultisample() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::attachTexture1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); Texture1D color; color.setStorage(1, TextureFormat::RGBA8, 128); @@ -531,7 +531,7 @@ void FramebufferGLTest::attachTexture1D() { void FramebufferGLTest::attachTexture2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif MAGNUM_VERIFY_NO_GL_ERROR(); @@ -602,10 +602,10 @@ void FramebufferGLTest::attachTexture2D() { void FramebufferGLTest::attachTexture3D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif Texture3D color; @@ -629,9 +629,9 @@ void FramebufferGLTest::attachTexture3D() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::attachTexture1DArray() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray color; color.setStorage(1, TextureFormat::RGBA8, {128, 8}); @@ -653,9 +653,9 @@ void FramebufferGLTest::attachTexture1DArray() { void FramebufferGLTest::attachTexture2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray color; @@ -678,9 +678,9 @@ void FramebufferGLTest::attachTexture2DArray() { void FramebufferGLTest::attachTexture2DMultisample() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -708,12 +708,12 @@ void FramebufferGLTest::attachTexture2DMultisample() { void FramebufferGLTest::attachTexture2DMultisampleArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); #endif MultisampleTexture2DArray color; @@ -739,9 +739,9 @@ void FramebufferGLTest::attachTexture2DMultisampleArray() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::attachRectangleTexture() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture color; color.setStorage(TextureFormat::RGBA8, Vector2i(128)); @@ -762,7 +762,7 @@ void FramebufferGLTest::attachRectangleTexture() { void FramebufferGLTest::attachCubeMapTexture() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Framebuffer framebuffer({{}, Vector2i(128)}); @@ -823,12 +823,12 @@ void FramebufferGLTest::attachCubeMapTexture() { void FramebufferGLTest::attachCubeMapTextureArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray color; @@ -851,12 +851,12 @@ void FramebufferGLTest::attachCubeMapTextureArray() { void FramebufferGLTest::attachLayeredTexture3D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::geometry_shader::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::geometry_shader::string() << "is not supported."); #endif Texture3D color; @@ -873,9 +873,9 @@ void FramebufferGLTest::attachLayeredTexture3D() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::attachLayeredTexture1DArray() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() << "is not supported."); Texture1DArray color; color.setStorage(1, TextureFormat::RGBA8, {128, 8}); @@ -896,12 +896,12 @@ void FramebufferGLTest::attachLayeredTexture1DArray() { void FramebufferGLTest::attachLayeredTexture2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::geometry_shader::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::geometry_shader::string() << "is not supported."); #endif Texture2DArray color; @@ -922,12 +922,12 @@ void FramebufferGLTest::attachLayeredTexture2DArray() { void FramebufferGLTest::attachLayeredCubeMapTexture() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::geometry_shader::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::geometry_shader::string() << "is not supported."); #endif CubeMapTexture color; @@ -948,16 +948,16 @@ void FramebufferGLTest::attachLayeredCubeMapTexture() { void FramebufferGLTest::attachLayeredCubeMapTextureArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::geometry_shader::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::geometry_shader::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif CubeMapTextureArray color; @@ -978,16 +978,16 @@ void FramebufferGLTest::attachLayeredCubeMapTextureArray() { void FramebufferGLTest::attachLayeredTexture2DMultisampleArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::geometry_shader4::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::geometry_shader::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::geometry_shader::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); #endif MultisampleTexture2DArray color; @@ -1013,7 +1013,7 @@ void FramebufferGLTest::attachLayeredTexture2DMultisampleArray() { void FramebufferGLTest::detach() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Framebuffer framebuffer({{}, Vector2i(128)}); @@ -1027,11 +1027,11 @@ void FramebufferGLTest::detach() { void FramebufferGLTest::multipleColorOutputs() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifdef MAGNUM_TARGET_WEBGL if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::draw_buffers::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::WEBGL::draw_buffers::string() << "is not supported."); #else if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) @@ -1095,7 +1095,7 @@ void FramebufferGLTest::multipleColorOutputs() { void FramebufferGLTest::clear() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -1368,7 +1368,7 @@ void FramebufferGLTest::clearDepthStencil() { void FramebufferGLTest::invalidate() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -1397,7 +1397,7 @@ void FramebufferGLTest::invalidate() { void FramebufferGLTest::invalidateSub() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -1429,7 +1429,7 @@ void FramebufferGLTest::read() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -1560,7 +1560,7 @@ void FramebufferGLTest::readView() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -1610,7 +1610,7 @@ void FramebufferGLTest::readViewNullptr() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -1638,7 +1638,7 @@ void FramebufferGLTest::readViewBadSize() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -1664,7 +1664,7 @@ void FramebufferGLTest::readViewBadSize() { void FramebufferGLTest::readBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer color; @@ -1712,7 +1712,7 @@ constexpr char ZeroStorage[4*4*4*6]{}; #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::copyImageTexture1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); Texture2D storage; storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1736,7 +1736,7 @@ void FramebufferGLTest::copyImageTexture1D() { void FramebufferGLTest::copyImageTexture2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Texture2D storage; @@ -1780,9 +1780,9 @@ void FramebufferGLTest::copyImageTexture2D() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::copyImageTexture1DArray() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture2D storage; storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1806,9 +1806,9 @@ void FramebufferGLTest::copyImageTexture1DArray() { void FramebufferGLTest::copyImageRectangleTexture() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); Texture2D storage; storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1834,7 +1834,7 @@ void FramebufferGLTest::copyImageRectangleTexture() { void FramebufferGLTest::copyImageCubeMapTexture() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES2 @@ -1885,7 +1885,7 @@ void FramebufferGLTest::copyImageCubeMapTexture() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::copySubImageTexture1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); Texture2D storage; storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1911,7 +1911,7 @@ void FramebufferGLTest::copySubImageTexture1D() { void FramebufferGLTest::copySubImageTexture2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Texture2D storage; @@ -1959,10 +1959,10 @@ void FramebufferGLTest::copySubImageTexture2D() { void FramebufferGLTest::copySubImageTexture3D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif Texture2D storage; @@ -2011,9 +2011,9 @@ void FramebufferGLTest::copySubImageTexture3D() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::copySubImageTexture1DArray() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture2D storage; storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -2043,9 +2043,9 @@ void FramebufferGLTest::copySubImageTexture1DArray() { void FramebufferGLTest::copySubImageTexture2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2D storage; @@ -2082,9 +2082,9 @@ void FramebufferGLTest::copySubImageTexture2DArray() { #ifndef MAGNUM_TARGET_GLES void FramebufferGLTest::copySubImageRectangleTexture() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); Texture2D storage; storage.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -2113,7 +2113,7 @@ void FramebufferGLTest::copySubImageRectangleTexture() { void FramebufferGLTest::copySubImageCubeMapTexture() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Texture2D storage; @@ -2161,12 +2161,12 @@ void FramebufferGLTest::copySubImageCubeMapTexture() { void FramebufferGLTest::copySubImageCubeMapTextureArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::texture_cube_map_array::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::texture_cube_map_array::string() << "is not supported."); #endif Texture2D storage; @@ -2224,7 +2224,7 @@ void FramebufferGLTest::copySubImageCubeMapTextureArray() { void FramebufferGLTest::blit() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) @@ -2277,7 +2277,7 @@ void FramebufferGLTest::implementationColorReadFormat() { #ifndef MAGNUM_TARGET_GLES if(data.integer && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::texture_integer::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::texture_integer::string() << "is not supported."); #endif Renderbuffer color; diff --git a/src/Magnum/GL/Test/MeshGLTest.cpp b/src/Magnum/GL/Test/MeshGLTest.cpp index 97dfee031..df17de288 100644 --- a/src/Magnum/GL/Test/MeshGLTest.cpp +++ b/src/Magnum/GL/Test/MeshGLTest.cpp @@ -468,10 +468,10 @@ void MeshGLTest::constructMove() { void MeshGLTest::wrap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::vertex_array_object::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::OES::vertex_array_object::string() << "is not supported."); #endif GLuint id; @@ -514,10 +514,10 @@ template void MeshGLTest::primitive() { void MeshGLTest::label() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::vertex_array_object::string() << "is not supported."); #endif /* No-Op version is tested in AbstractObjectGLTest */ @@ -730,7 +730,7 @@ template T Checker::get(PixelFormat format, PixelType type) { void MeshGLTest::addVertexBufferUnsignedInt() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif constexpr UnsignedInt data[] = { 0, 157, 35681 }; @@ -763,7 +763,7 @@ void MeshGLTest::addVertexBufferUnsignedInt() { void MeshGLTest::addVertexBufferInt() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif constexpr Int data[] = { 0, 457931, 27530 }; @@ -843,7 +843,7 @@ void MeshGLTest::addVertexBufferFloat() { #ifndef MAGNUM_TARGET_GLES void MeshGLTest::addVertexBufferDouble() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() << "is not supported."); const Double data[] = { 0.0, -0.7, Math::unpack(45828) }; Buffer buffer; @@ -877,7 +877,7 @@ void MeshGLTest::addVertexBufferDouble() { void MeshGLTest::addVertexBufferVectorNui() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif constexpr Vector3ui data[] = { {}, {37448, 547686, 156}, {27592, 157, 25} }; @@ -910,7 +910,7 @@ void MeshGLTest::addVertexBufferVectorNui() { void MeshGLTest::addVertexBufferVectorNi() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif constexpr Vector2i data[] = { {}, {-37448, 547686}, {27592, -157} }; @@ -990,7 +990,7 @@ void MeshGLTest::addVertexBufferVectorN() { #ifndef MAGNUM_TARGET_GLES void MeshGLTest::addVertexBufferVectorNd() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() << "is not supported."); const Vector4d data[] = { {}, {0.0, -0.9, 1.0, 1.25}, @@ -1077,7 +1077,7 @@ void MeshGLTest::addVertexBufferMatrixNxN() { #ifndef MAGNUM_TARGET_GLES void MeshGLTest::addVertexBufferMatrixNxNd() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() << "is not supported."); const Matrix3x3d data[] = { {}, @@ -1161,7 +1161,7 @@ void MeshGLTest::addVertexBufferMatrixMxN() { #ifndef MAGNUM_TARGET_GLES void MeshGLTest::addVertexBufferMatrixMxNd() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() << "is not supported."); const Matrix3x4d data[] = { {}, @@ -1211,7 +1211,7 @@ void MeshGLTest::addVertexBufferMatrixMxNd() { void MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif constexpr UnsignedShort data[] = { 0, 49563, 2128, 3821, 16583 }; @@ -1249,7 +1249,7 @@ void MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort() { void MeshGLTest::addVertexBufferUnsignedIntWithShort() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif constexpr Short data[] = { 0, 24563, 2128, 3821, 16583 }; @@ -1287,7 +1287,7 @@ void MeshGLTest::addVertexBufferUnsignedIntWithShort() { void MeshGLTest::addVertexBufferIntWithUnsignedShort() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif constexpr UnsignedShort data[] = { 0, 49563, 2128, 3821, 16583 }; @@ -1325,7 +1325,7 @@ void MeshGLTest::addVertexBufferIntWithUnsignedShort() { void MeshGLTest::addVertexBufferIntWithShort() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif constexpr Short data[] = { 0, 24563, 2128, 3821, -16583 }; @@ -1365,10 +1365,10 @@ void MeshGLTest::addVertexBufferIntWithShort() { void MeshGLTest::addVertexBufferFloatWithHalf() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::half_float_vertex::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::half_float_vertex::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::vertex_half_float::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::vertex_half_float::string() << "is not supported."); #endif const Half data[] = { 0.0_h, -0.7_h, Half(Math::unpack(186)) }; @@ -1432,7 +1432,7 @@ void MeshGLTest::addVertexBufferFloatWithDouble() { void MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_type_10f_11f_11f_rev::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_type_10f_11f_11f_rev::string() << "is not supported."); #endif Buffer buffer; @@ -1461,7 +1461,7 @@ void MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev() { void MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_type_2_10_10_10_rev::string() << "is not supported."); #endif Buffer buffer; @@ -1488,7 +1488,7 @@ void MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev() { void MeshGLTest::addVertexBufferVector4WithInt2101010Rev() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_type_2_10_10_10_rev::string() << "is not supported."); #endif Buffer buffer; @@ -1610,7 +1610,7 @@ void MeshGLTest::addVertexBufferNormalized() { #ifndef MAGNUM_TARGET_GLES void MeshGLTest::addVertexBufferBGRA() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_array_bgra::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_array_bgra::string() << "is not supported."); constexpr Color4ub data[] = { {}, {0, 128, 64, 161}, {96, 24, 156, 225} }; Buffer buffer; @@ -1870,7 +1870,7 @@ void MeshGLTest::addVertexBufferTransferOwnwership() { void MeshGLTest::addVertexBufferInstancedTransferOwnwership() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!Context::current().isExtensionSupported() && @@ -1879,7 +1879,7 @@ void MeshGLTest::addVertexBufferInstancedTransferOwnwership() { CORRADE_SKIP("Required extension is not available."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif @@ -1945,7 +1945,7 @@ void MeshGLTest::addVertexBufferDynamicTransferOwnwership() { void MeshGLTest::addVertexBufferInstancedDynamicTransferOwnwership() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!Context::current().isExtensionSupported() && @@ -1954,7 +1954,7 @@ void MeshGLTest::addVertexBufferInstancedDynamicTransferOwnwership() { CORRADE_SKIP("Required extension is not available."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif @@ -2120,7 +2120,7 @@ template void MeshGLTest::setIndexBufferRange() { void MeshGLTest::setIndexBufferUnsignedInt() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::element_index_uint::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::element_index_uint::string() << "is not supported."); #endif Buffer vertices; @@ -2232,12 +2232,12 @@ template void MeshGLTest::setIndexBufferRangeTransferOwnership() { void MeshGLTest::unbindVAOWhenSettingIndexBufferData() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() << "is not supported."); if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is active which circumvents the issue tested here.")); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::vertex_array_object::string() << "is not supported."); #endif typedef Attribute<0, Float> Attribute; @@ -2287,12 +2287,12 @@ void MeshGLTest::unbindVAOWhenSettingIndexBufferData() { void MeshGLTest::unbindIndexBufferWhenBindingVao() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() << "is not supported."); if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is active which circumvents the issue tested here.")); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::vertex_array_object::string() << "is not supported."); #endif typedef Attribute<0, Float> Attribute; @@ -2349,12 +2349,12 @@ void MeshGLTest::unbindIndexBufferWhenBindingVao() { void MeshGLTest::resetIndexBufferBindingWhenBindingVao() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() << "is not supported."); if(Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::direct_state_access::string() + std::string(" is active which circumvents the issue tested here.")); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::vertex_array_object::string() << "is not supported."); #endif typedef Attribute<0, Float> Attribute; @@ -2409,10 +2409,10 @@ void MeshGLTest::resetIndexBufferBindingWhenBindingVao() { void MeshGLTest::unbindVAOBeforeEnteringExternalSection() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_array_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::vertex_array_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::OES::vertex_array_object::string() << "is not supported."); #endif typedef Attribute<0, Float> Attribute; @@ -2539,7 +2539,7 @@ void MeshGLTest::bindScratchVaoWhenEnteringExternalSection() { void MeshGLTest::setBaseVertex() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) @@ -2646,7 +2646,7 @@ void MeshGLTest::setInstanceCount() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!Context::current().isExtensionSupported() && @@ -2657,7 +2657,7 @@ void MeshGLTest::setInstanceCount() { CORRADE_SKIP("Required extension is not available."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif @@ -2695,9 +2695,9 @@ void MeshGLTest::setInstanceCountBaseInstance() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::base_instance::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::base_instance::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is not available."}); @@ -2759,7 +2759,7 @@ void MeshGLTest::setInstanceCountIndexed() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!Context::current().isExtensionSupported() && @@ -2770,7 +2770,7 @@ void MeshGLTest::setInstanceCountIndexed() { CORRADE_SKIP("Required extension is not available."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif @@ -2810,9 +2810,9 @@ void MeshGLTest::setInstanceCountIndexedBaseInstance() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::base_instance::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::base_instance::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is not available."}); @@ -2881,9 +2881,9 @@ void MeshGLTest::setInstanceCountIndexedBaseVertex() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) @@ -2963,11 +2963,11 @@ void MeshGLTest::setInstanceCountIndexedBaseVertexBaseInstance() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::base_instance::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::base_instance::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is not available."}); @@ -3036,9 +3036,9 @@ void MeshGLTest::setInstanceCountIndexedBaseVertexBaseInstanceNoExtensionAvailab void MeshGLTest::addVertexBufferInstancedFloat() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::instanced_arrays::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!Context::current().isExtensionSupported() && @@ -3047,7 +3047,7 @@ void MeshGLTest::addVertexBufferInstancedFloat() { CORRADE_SKIP("Required extension is not available."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif @@ -3085,11 +3085,11 @@ void MeshGLTest::addVertexBufferInstancedFloat() { void MeshGLTest::addVertexBufferInstancedInteger() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::instanced_arrays::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif typedef Attribute<0, UnsignedInt> Attribute; @@ -3121,11 +3121,11 @@ void MeshGLTest::addVertexBufferInstancedInteger() { #ifndef MAGNUM_TARGET_GLES void MeshGLTest::addVertexBufferInstancedDouble() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::instanced_arrays::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::vertex_attrib_64bit::string() << "is not supported."); typedef Attribute<0, Double> Attribute; @@ -3156,9 +3156,9 @@ void MeshGLTest::addVertexBufferInstancedDouble() { void MeshGLTest::resetDivisorAfterInstancedDraw() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_instanced::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::instanced_arrays::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!Context::current().isExtensionSupported() && @@ -3167,7 +3167,7 @@ void MeshGLTest::resetDivisorAfterInstancedDraw() { CORRADE_SKIP("Required extension is not available."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif @@ -3377,7 +3377,7 @@ void MeshGLTest::multiDrawInstanced() { void MeshGLTest::multiDrawBaseVertex() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() << "is not supported."); #elif !defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) diff --git a/src/Magnum/GL/Test/MultisampleTextureGLTest.cpp b/src/Magnum/GL/Test/MultisampleTextureGLTest.cpp index d9553b1e1..58ba63a19 100644 --- a/src/Magnum/GL/Test/MultisampleTextureGLTest.cpp +++ b/src/Magnum/GL/Test/MultisampleTextureGLTest.cpp @@ -90,7 +90,7 @@ MultisampleTextureGLTest::MultisampleTextureGLTest() { void MultisampleTextureGLTest::construct2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -109,10 +109,10 @@ void MultisampleTextureGLTest::construct2D() { void MultisampleTextureGLTest::construct2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); #endif { @@ -137,7 +137,7 @@ void MultisampleTextureGLTest::constructMove() { void MultisampleTextureGLTest::wrap2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string{" is not supported."}); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -160,10 +160,10 @@ void MultisampleTextureGLTest::wrap2D() { void MultisampleTextureGLTest::wrap2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); #endif GLuint id; @@ -183,7 +183,7 @@ void MultisampleTextureGLTest::wrap2DArray() { void MultisampleTextureGLTest::bind2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -210,10 +210,10 @@ void MultisampleTextureGLTest::bind2D() { void MultisampleTextureGLTest::bind2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); #endif MultisampleTexture2DArray texture; @@ -237,12 +237,12 @@ void MultisampleTextureGLTest::bind2DArray() { void MultisampleTextureGLTest::bindImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); #endif @@ -273,12 +273,12 @@ void MultisampleTextureGLTest::bindImage2D() { void MultisampleTextureGLTest::bindImage2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); #endif @@ -312,7 +312,7 @@ void MultisampleTextureGLTest::bindImage2DArray() { void MultisampleTextureGLTest::storage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -333,10 +333,10 @@ void MultisampleTextureGLTest::storage2D() { void MultisampleTextureGLTest::storage2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); #endif MultisampleTexture2DArray texture; @@ -354,7 +354,7 @@ void MultisampleTextureGLTest::storage2DArray() { void MultisampleTextureGLTest::invalidateImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -372,10 +372,10 @@ void MultisampleTextureGLTest::invalidateImage2D() { void MultisampleTextureGLTest::invalidateImage2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); #endif MultisampleTexture2DArray texture; @@ -390,7 +390,7 @@ void MultisampleTextureGLTest::invalidateImage2DArray() { void MultisampleTextureGLTest::invalidateSubImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -408,10 +408,10 @@ void MultisampleTextureGLTest::invalidateSubImage2D() { void MultisampleTextureGLTest::invalidateSubImage2DArray() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_multisample::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_multisample::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_storage_multisample_2d_array::string() << "is not supported."); #endif MultisampleTexture2DArray texture; diff --git a/src/Magnum/GL/Test/PipelineStatisticsQueryGLTest.cpp b/src/Magnum/GL/Test/PipelineStatisticsQueryGLTest.cpp index 6d771cc0f..fe20bc2d4 100644 --- a/src/Magnum/GL/Test/PipelineStatisticsQueryGLTest.cpp +++ b/src/Magnum/GL/Test/PipelineStatisticsQueryGLTest.cpp @@ -66,7 +66,7 @@ void PipelineStatisticsQueryGLTest::constructMove() { void PipelineStatisticsQueryGLTest::wrap() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::pipeline_statistics_query::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::ARB::pipeline_statistics_query::string() << "is not available"); GLuint id; glGenQueries(1, &id); @@ -84,7 +84,7 @@ void PipelineStatisticsQueryGLTest::wrap() { void PipelineStatisticsQueryGLTest::queryVerticesSubmitted() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::pipeline_statistics_query::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::ARB::pipeline_statistics_query::string() << "is not available"); /* Bind some FB to avoid errors on contexts w/o default FB */ Renderbuffer color; diff --git a/src/Magnum/GL/Test/PixelStorageGLTest.cpp b/src/Magnum/GL/Test/PixelStorageGLTest.cpp index c69f68392..5bb4d1809 100644 --- a/src/Magnum/GL/Test/PixelStorageGLTest.cpp +++ b/src/Magnum/GL/Test/PixelStorageGLTest.cpp @@ -102,7 +102,7 @@ constexpr const char ActualData[] = { void PixelStorageGLTest::unpack2D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() << "is not supported."); #endif ImageView2D image{PixelStorage{} @@ -142,7 +142,7 @@ void PixelStorageGLTest::unpack2D() { void PixelStorageGLTest::pack2D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::NV::pack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::NV::pack_subimage::string() << "is not supported."); #endif ImageView2D actual{PixelFormat::RGB, PixelType::UnsignedByte, {2, 3}, ActualData}; @@ -287,7 +287,7 @@ constexpr const UnsignedByte ActualCompressedData[] = { void PixelStorageGLTest::unpackCompressed2D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CompressedPixelStorage storage; storage.setCompressedBlockSize({4, 4, 1}) @@ -314,7 +314,7 @@ void PixelStorageGLTest::unpackCompressed2D() { void PixelStorageGLTest::packCompressed2D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CompressedImageView2D actual{CompressedPixelFormat::RGBAS3tcDxt3, {4, 4}, ActualCompressedData}; @@ -393,7 +393,7 @@ constexpr const UnsignedByte CompressedData3D[] = { void PixelStorageGLTest::unpackCompressed3D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CompressedPixelStorage storage; storage.setCompressedBlockSize({4, 4, 1}) @@ -421,7 +421,7 @@ void PixelStorageGLTest::unpackCompressed3D() { void PixelStorageGLTest::packCompressed3D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CompressedImageView3D actual{CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 1}, ActualCompressedData}; diff --git a/src/Magnum/GL/Test/PrimitiveQueryGLTest.cpp b/src/Magnum/GL/Test/PrimitiveQueryGLTest.cpp index 719837149..a04f5f121 100644 --- a/src/Magnum/GL/Test/PrimitiveQueryGLTest.cpp +++ b/src/Magnum/GL/Test/PrimitiveQueryGLTest.cpp @@ -96,7 +96,7 @@ void PrimitiveQueryGLTest::constructMove() { void PrimitiveQueryGLTest::wrap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif GLuint id; @@ -117,10 +117,10 @@ void PrimitiveQueryGLTest::wrap() { void PrimitiveQueryGLTest::primitivesGenerated() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::transform_feedback::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::transform_feedback::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::geometry_shader::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::geometry_shader::string() << "is not supported."); #endif /* Bind some FB to avoid errors on contexts w/o default FB */ @@ -199,7 +199,7 @@ void PrimitiveQueryGLTest::primitivesGenerated() { #ifndef MAGNUM_TARGET_GLES void PrimitiveQueryGLTest::primitivesGeneratedIndexed() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback3::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback3::string() << "is not supported."); /* Bind some FB to avoid errors on contexts w/o default FB */ Renderbuffer color; @@ -262,7 +262,7 @@ void PrimitiveQueryGLTest::primitivesGeneratedIndexed() { void PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif /* Bind some FB to avoid errors on contexts w/o default FB */ @@ -341,7 +341,7 @@ void PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten() { void PrimitiveQueryGLTest::transformFeedbackOverflow() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback_overflow_query::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback_overflow_query::string() << "is not supported."); #endif /* Bind some FB to avoid errors on contexts w/o default FB */ diff --git a/src/Magnum/GL/Test/RectangleTextureGLTest.cpp b/src/Magnum/GL/Test/RectangleTextureGLTest.cpp index 0688f2fa5..59ea5a6eb 100644 --- a/src/Magnum/GL/Test/RectangleTextureGLTest.cpp +++ b/src/Magnum/GL/Test/RectangleTextureGLTest.cpp @@ -157,7 +157,7 @@ RectangleTextureGLTest::RectangleTextureGLTest() { void RectangleTextureGLTest::construct() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); { RectangleTexture texture; @@ -180,7 +180,7 @@ void RectangleTextureGLTest::constructMove() { void RectangleTextureGLTest::wrap() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); GLuint id; glGenTextures(1, &id); @@ -198,7 +198,7 @@ void RectangleTextureGLTest::wrap() { void RectangleTextureGLTest::bind() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.bind(15); @@ -220,9 +220,9 @@ void RectangleTextureGLTest::bind() { void RectangleTextureGLTest::bindImage() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); RectangleTexture texture; texture.setStorage(TextureFormat::RGBA8, Vector2i{32}) @@ -248,7 +248,7 @@ template void RectangleTextureGLTest::sampling() { "GenericSampler" : "GLSampler"); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setMinificationFilter(T::Filter::Linear) @@ -264,9 +264,9 @@ template void RectangleTextureGLTest::sampling() { void RectangleTextureGLTest::samplingSrgbDecode() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() << "is not supported."); RectangleTexture texture; texture.setSrgbDecode(false); @@ -276,9 +276,9 @@ void RectangleTextureGLTest::samplingSrgbDecode() { void RectangleTextureGLTest::samplingBorderInteger() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_integer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_integer::string() << "is not supported."); RectangleTexture a; a.setWrapping(SamplerWrapping::ClampToBorder) @@ -292,9 +292,9 @@ void RectangleTextureGLTest::samplingBorderInteger() { void RectangleTextureGLTest::samplingSwizzle() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() << "is not supported."); RectangleTexture texture; texture.setSwizzle<'b', 'g', 'r', '0'>(); @@ -304,9 +304,9 @@ void RectangleTextureGLTest::samplingSwizzle() { void RectangleTextureGLTest::samplingDepthStencilMode() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() << "is not supported."); RectangleTexture texture; texture.setDepthStencilMode(SamplerDepthStencilMode::StencilIndex); @@ -316,7 +316,7 @@ void RectangleTextureGLTest::samplingDepthStencilMode() { void RectangleTextureGLTest::storage() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setStorage(TextureFormat::RGBA8, Vector2i(32)); @@ -332,7 +332,7 @@ void RectangleTextureGLTest::image() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setImage(TextureFormat::RGBA8, ImageView2D{ @@ -357,7 +357,7 @@ void RectangleTextureGLTest::imageBuffer() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setImage(TextureFormat::RGBA8, BufferImage2D{ @@ -384,7 +384,7 @@ void RectangleTextureGLTest::imageQueryView() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setImage(TextureFormat::RGBA8, ImageView2D{ @@ -418,7 +418,7 @@ void RectangleTextureGLTest::subImage() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setImage(TextureFormat::RGBA8, @@ -443,7 +443,7 @@ void RectangleTextureGLTest::subImageBuffer() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setImage(TextureFormat::RGBA8, @@ -471,9 +471,9 @@ void RectangleTextureGLTest::subImageQuery() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); RectangleTexture texture; texture.setStorage(TextureFormat::RGBA8, Vector2i{4}) @@ -497,9 +497,9 @@ void RectangleTextureGLTest::subImageQueryView() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); RectangleTexture texture; texture.setStorage(TextureFormat::RGBA8, Vector2i{4}) @@ -523,9 +523,9 @@ void RectangleTextureGLTest::subImageQueryBuffer() { setTestCaseDescription(PixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); RectangleTexture texture; texture.setStorage(TextureFormat::RGBA8, Vector2i{4}) @@ -580,7 +580,7 @@ void RectangleTextureGLTest::compressedSubImageQueryBuffer() { void RectangleTextureGLTest::invalidateImage() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setStorage(TextureFormat::RGBA8, Vector2i(32)); @@ -591,7 +591,7 @@ void RectangleTextureGLTest::invalidateImage() { void RectangleTextureGLTest::invalidateSubImage() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_rectangle::string() << "is not supported."); RectangleTexture texture; texture.setStorage(TextureFormat::RGBA8, Vector2i(32)); diff --git a/src/Magnum/GL/Test/RenderbufferGLTest.cpp b/src/Magnum/GL/Test/RenderbufferGLTest.cpp index e8fd94189..9b6752017 100644 --- a/src/Magnum/GL/Test/RenderbufferGLTest.cpp +++ b/src/Magnum/GL/Test/RenderbufferGLTest.cpp @@ -71,7 +71,7 @@ RenderbufferGLTest::RenderbufferGLTest() { void RenderbufferGLTest::construct() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif { @@ -87,7 +87,7 @@ void RenderbufferGLTest::construct() { void RenderbufferGLTest::constructMove() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer a; @@ -117,7 +117,7 @@ void RenderbufferGLTest::constructMove() { void RenderbufferGLTest::wrap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif GLuint id; @@ -138,7 +138,7 @@ void RenderbufferGLTest::wrap() { void RenderbufferGLTest::label() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) @@ -159,7 +159,7 @@ void RenderbufferGLTest::label() { void RenderbufferGLTest::setStorage() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Renderbuffer renderbuffer; @@ -177,7 +177,7 @@ void RenderbufferGLTest::setStorage() { void RenderbufferGLTest::setStorageMultisample() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) diff --git a/src/Magnum/GL/Test/RendererGLTest.cpp b/src/Magnum/GL/Test/RendererGLTest.cpp index e469c4c62..7fafe2d71 100644 --- a/src/Magnum/GL/Test/RendererGLTest.cpp +++ b/src/Magnum/GL/Test/RendererGLTest.cpp @@ -240,10 +240,10 @@ void RendererGLTest::pointCoord() { void RendererGLTest::patchParameters() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::tessellation_shader::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::tessellation_shader::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::tessellation_shader::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::tessellation_shader::string() << "is not supported."); #endif /* All we can do is check for GL errors */ @@ -260,10 +260,10 @@ void RendererGLTest::patchParameters() { void RendererGLTest::drawBuffersIndexed() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::draw_buffers2::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::draw_buffers2::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::draw_buffers_indexed::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::draw_buffers_indexed::string() << "is not supported."); #endif /* Call the draw-buffer dependent functions, only expect that no GL error @@ -277,10 +277,10 @@ void RendererGLTest::drawBuffersIndexed() { void RendererGLTest::drawBuffersBlend() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::draw_buffers_blend::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::ARB::draw_buffers_blend::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::draw_buffers_indexed::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::draw_buffers_indexed::string() << "is not supported."); #endif /* Call the draw-buffer dependent functions, only expect that no GL error diff --git a/src/Magnum/GL/Test/SampleQueryGLTest.cpp b/src/Magnum/GL/Test/SampleQueryGLTest.cpp index 99b1c752e..cc28390fd 100644 --- a/src/Magnum/GL/Test/SampleQueryGLTest.cpp +++ b/src/Magnum/GL/Test/SampleQueryGLTest.cpp @@ -76,7 +76,7 @@ void SampleQueryGLTest::constructMove() { void SampleQueryGLTest::wrap() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() << "is not supported."); #endif GLuint id; @@ -161,7 +161,7 @@ MyShader::MyShader() { void SampleQueryGLTest::querySamplesPassed() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::EXT::occlusion_query_boolean::string() << "is not supported."); #endif Renderbuffer renderbuffer; @@ -219,7 +219,7 @@ void SampleQueryGLTest::querySamplesPassed() { #ifndef MAGNUM_TARGET_GLES void SampleQueryGLTest::conditionalRender() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::NV::conditional_render::string() + std::string(" is not available.")); + CORRADE_SKIP(Extensions::NV::conditional_render::string() << "is not supported."); Renderbuffer renderbuffer; renderbuffer.setStorage(RenderbufferFormat::RGBA8, Vector2i(32)); diff --git a/src/Magnum/GL/Test/TextureArrayGLTest.cpp b/src/Magnum/GL/Test/TextureArrayGLTest.cpp index d0f607a87..7b23c50a0 100644 --- a/src/Magnum/GL/Test/TextureArrayGLTest.cpp +++ b/src/Magnum/GL/Test/TextureArrayGLTest.cpp @@ -409,7 +409,7 @@ TextureArrayGLTest::TextureArrayGLTest() { #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::construct1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); { Texture1DArray texture; @@ -425,7 +425,7 @@ void TextureArrayGLTest::construct1D() { void TextureArrayGLTest::construct2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif { @@ -467,7 +467,7 @@ void TextureArrayGLTest::wrap1D() { void TextureArrayGLTest::wrap2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif GLuint id; @@ -487,7 +487,7 @@ void TextureArrayGLTest::wrap2D() { #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::bind1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.bind(15); @@ -511,7 +511,7 @@ void TextureArrayGLTest::bind1D() { void TextureArrayGLTest::bind2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -536,7 +536,7 @@ void TextureArrayGLTest::bind2D() { #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::bindImage1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); Texture1DArray texture; texture.setStorage(1, TextureFormat::RGBA8, {32, 4}) @@ -564,7 +564,7 @@ void TextureArrayGLTest::bindImage1D() { void TextureArrayGLTest::bindImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -601,7 +601,7 @@ template void TextureArrayGLTest::sampling1D() { "GenericSampler" : "GLSampler"); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setMinificationFilter(T::Filter::Linear, T::Mipmap::Linear) @@ -622,9 +622,9 @@ template void TextureArrayGLTest::sampling1D() { void TextureArrayGLTest::samplingSrgbDecode1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() << "is not supported."); Texture1DArray texture; texture.setSrgbDecode(false); @@ -634,9 +634,9 @@ void TextureArrayGLTest::samplingSrgbDecode1D() { void TextureArrayGLTest::samplingSwizzle1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() << "is not supported."); Texture1DArray texture; texture.setSwizzle<'b', 'g', 'r', '0'>(); @@ -646,9 +646,9 @@ void TextureArrayGLTest::samplingSwizzle1D() { void TextureArrayGLTest::samplingBorderInteger1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_integer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_integer::string() << "is not supported."); Texture1DArray a; a.setWrapping(SamplerWrapping::ClampToBorder) @@ -662,9 +662,9 @@ void TextureArrayGLTest::samplingBorderInteger1D() { void TextureArrayGLTest::samplingDepthStencilMode1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() << "is not supported."); Texture1DArray texture; texture.setDepthStencilMode(SamplerDepthStencilMode::StencilIndex); @@ -679,7 +679,7 @@ template void TextureArrayGLTest::sampling2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -714,10 +714,10 @@ template void TextureArrayGLTest::sampling2D() { void TextureArrayGLTest::samplingSrgbDecode2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() << "is not supported."); Texture2DArray texture; texture.setSrgbDecode(false); @@ -730,9 +730,9 @@ void TextureArrayGLTest::samplingSrgbDecode2D() { void TextureArrayGLTest::samplingSwizzle2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() << "is not supported."); #endif Texture2DArray texture; @@ -745,7 +745,7 @@ void TextureArrayGLTest::samplingSwizzle2D() { #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void TextureArrayGLTest::samplingMaxLevel2D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::APPLE::texture_max_level::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::APPLE::texture_max_level::string() << "is not supported."); Texture2DArray texture; texture.setMaxLevel(750); @@ -756,7 +756,7 @@ void TextureArrayGLTest::samplingMaxLevel2D() { void TextureArrayGLTest::samplingCompare2D() { if(!Context::current().isExtensionSupported() || !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::NV::shadow_samplers_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::NV::shadow_samplers_array::string() << "is not supported."); Texture2DArray texture; texture.setCompareMode(SamplerCompareMode::CompareRefToTexture) @@ -770,12 +770,12 @@ void TextureArrayGLTest::samplingCompare2D() { void TextureArrayGLTest::samplingBorderInteger2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_integer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_integer::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() << "is not supported."); #endif Texture2DArray a; @@ -793,9 +793,9 @@ void TextureArrayGLTest::samplingBorderInteger2D() { void TextureArrayGLTest::samplingDepthStencilMode2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -825,7 +825,7 @@ void TextureArrayGLTest::samplingBorder2D() { #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::storage1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setStorage(5, TextureFormat::RGBA8, Vector2i(32)); @@ -846,7 +846,7 @@ void TextureArrayGLTest::storage1D() { void TextureArrayGLTest::storage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -876,7 +876,7 @@ void TextureArrayGLTest::image1D() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setImage(0, TextureFormat::RGBA8, ImageView2D{ @@ -900,7 +900,7 @@ void TextureArrayGLTest::image1DBuffer() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setImage(0, TextureFormat::RGBA8, BufferImage2D{ @@ -927,7 +927,7 @@ void TextureArrayGLTest::image1DQueryView() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setImage(0, TextureFormat::RGBA8, ImageView2D{ @@ -961,7 +961,7 @@ void TextureArrayGLTest::subImage1D() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setImage(0, TextureFormat::RGBA8, @@ -986,7 +986,7 @@ void TextureArrayGLTest::subImage1DBuffer() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setImage(0, TextureFormat::RGBA8, @@ -1014,9 +1014,9 @@ void TextureArrayGLTest::subImage1DQuery() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture1DArray texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1040,9 +1040,9 @@ void TextureArrayGLTest::subImage1DQueryView() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture1DArray texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1067,9 +1067,9 @@ void TextureArrayGLTest::subImage1DQueryBuffer() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture1DArray texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1130,7 +1130,7 @@ void TextureArrayGLTest::image2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -1160,7 +1160,7 @@ void TextureArrayGLTest::image2DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -1192,7 +1192,7 @@ void TextureArrayGLTest::image2DQueryView() { setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture2DArray texture; texture.setImage(0, TextureFormat::RGBA8, ImageView3D{ @@ -1247,7 +1247,7 @@ void TextureArrayGLTest::subImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -1278,7 +1278,7 @@ void TextureArrayGLTest::subImage2DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -1311,9 +1311,9 @@ void TextureArrayGLTest::subImage2DQuery() { setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture2DArray texture; texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) @@ -1337,9 +1337,9 @@ void TextureArrayGLTest::subImage2DQueryView() { setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture2DArray texture; texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) @@ -1364,9 +1364,9 @@ void TextureArrayGLTest::subImage2DQueryBuffer() { setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture2DArray texture; texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) @@ -1393,22 +1393,22 @@ void TextureArrayGLTest::compressedImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif Texture2DArray texture; @@ -1438,22 +1438,22 @@ void TextureArrayGLTest::compressedImage2DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif Texture2DArray texture; @@ -1485,12 +1485,12 @@ void TextureArrayGLTest::compressedImage2DQueryView() { setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); Texture2DArray texture; texture.setCompressedImage(0, CompressedImageView3D{ @@ -1554,22 +1554,22 @@ void TextureArrayGLTest::compressedSubImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif Texture2DArray texture; @@ -1607,22 +1607,22 @@ void TextureArrayGLTest::compressedSubImage2DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif Texture2DArray texture; @@ -1656,15 +1656,15 @@ void TextureArrayGLTest::compressedSubImage2DQuery() { setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2DArray texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 4, 4}) @@ -1687,15 +1687,15 @@ void TextureArrayGLTest::compressedSubImage2DQueryView() { setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2DArray texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 4, 4}) @@ -1720,15 +1720,15 @@ void TextureArrayGLTest::compressedSubImage2DQueryBuffer() { setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2DArray texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 4, 4}) @@ -1754,9 +1754,9 @@ void TextureArrayGLTest::compressedSubImage2DQueryBuffer() { void TextureArrayGLTest::generateMipmap1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setImage(0, TextureFormat::RGBA8, @@ -1783,9 +1783,9 @@ void TextureArrayGLTest::generateMipmap1D() { void TextureArrayGLTest::generateMipmap2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -1817,7 +1817,7 @@ void TextureArrayGLTest::generateMipmap2D() { #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::invalidateImage1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setStorage(2, TextureFormat::RGBA8, Vector2i(32)); @@ -1830,7 +1830,7 @@ void TextureArrayGLTest::invalidateImage1D() { void TextureArrayGLTest::invalidateImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; @@ -1843,7 +1843,7 @@ void TextureArrayGLTest::invalidateImage2D() { #ifndef MAGNUM_TARGET_GLES void TextureArrayGLTest::invalidateSubImage1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); Texture1DArray texture; texture.setStorage(2, TextureFormat::RGBA8, Vector2i(32)); @@ -1856,7 +1856,7 @@ void TextureArrayGLTest::invalidateSubImage1D() { void TextureArrayGLTest::invalidateSubImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_array::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_array::string() << "is not supported."); #endif Texture2DArray texture; diff --git a/src/Magnum/GL/Test/TextureGLTest.cpp b/src/Magnum/GL/Test/TextureGLTest.cpp index 84c88b87b..7f78282d1 100644 --- a/src/Magnum/GL/Test/TextureGLTest.cpp +++ b/src/Magnum/GL/Test/TextureGLTest.cpp @@ -680,7 +680,7 @@ void TextureGLTest::construct2D() { void TextureGLTest::construct3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif { @@ -739,7 +739,7 @@ void TextureGLTest::wrap2D() { void TextureGLTest::wrap3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif GLuint id; @@ -801,7 +801,7 @@ void TextureGLTest::bind2D() { void TextureGLTest::bind3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif Texture3D texture; @@ -827,7 +827,7 @@ void TextureGLTest::bind3D() { #ifndef MAGNUM_TARGET_GLES void TextureGLTest::bindImage1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); Texture1D texture; texture.setStorage(1, TextureFormat::RGBA8, 32) @@ -852,7 +852,7 @@ void TextureGLTest::bindImage1D() { void TextureGLTest::bindImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -882,7 +882,7 @@ void TextureGLTest::bindImage2D() { void TextureGLTest::bindImage3D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::shader_image_load_store::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -937,7 +937,7 @@ template void TextureGLTest::sampling1D() { void TextureGLTest::samplingSrgbDecode1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() << "is not supported."); Texture1D texture; texture.setSrgbDecode(false); @@ -947,7 +947,7 @@ void TextureGLTest::samplingSrgbDecode1D() { void TextureGLTest::samplingSwizzle1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() << "is not supported."); Texture1D texture; texture.setSwizzle<'b', 'g', 'r', '0'>(); @@ -957,7 +957,7 @@ void TextureGLTest::samplingSwizzle1D() { void TextureGLTest::samplingBorderInteger1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_integer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_integer::string() << "is not supported."); Texture1D a; a.setWrapping(SamplerWrapping::ClampToBorder) @@ -971,7 +971,7 @@ void TextureGLTest::samplingBorderInteger1D() { void TextureGLTest::samplingDepthStencilMode1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() << "is not supported."); Texture1D texture; texture.setDepthStencilMode(SamplerDepthStencilMode::StencilIndex); @@ -1016,10 +1016,10 @@ template void TextureGLTest::sampling2D() { void TextureGLTest::samplingSrgbDecode2D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::sRGB::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::sRGB::string() << "is not supported."); #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() << "is not supported."); Texture2D texture; texture.setSrgbDecode(false); @@ -1032,7 +1032,7 @@ void TextureGLTest::samplingSrgbDecode2D() { void TextureGLTest::samplingSwizzle2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() << "is not supported."); #endif Texture2D texture; @@ -1045,7 +1045,7 @@ void TextureGLTest::samplingSwizzle2D() { #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void TextureGLTest::samplingMaxLevel2D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::APPLE::texture_max_level::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::APPLE::texture_max_level::string() << "is not supported."); Texture2D texture; texture.setMaxLevel(750); @@ -1055,7 +1055,7 @@ void TextureGLTest::samplingMaxLevel2D() { void TextureGLTest::samplingCompare2D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::shadow_samplers::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::shadow_samplers::string() << "is not supported."); Texture2D texture; texture.setCompareMode(SamplerCompareMode::CompareRefToTexture) @@ -1069,10 +1069,10 @@ void TextureGLTest::samplingCompare2D() { void TextureGLTest::samplingBorderInteger2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_integer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_integer::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() << "is not supported."); #endif Texture2D a; @@ -1088,7 +1088,7 @@ void TextureGLTest::samplingBorderInteger2D() { void TextureGLTest::samplingDepthStencilMode2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -1122,7 +1122,7 @@ template void TextureGLTest::sampling3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif Texture3D texture; @@ -1152,12 +1152,12 @@ template void TextureGLTest::sampling3D() { void TextureGLTest::samplingSrgbDecode3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::sRGB::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::sRGB::string() << "is not supported."); #endif if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_sRGB_decode::string() << "is not supported."); Texture3D texture; texture.setSrgbDecode(false); @@ -1170,7 +1170,7 @@ void TextureGLTest::samplingSrgbDecode3D() { void TextureGLTest::samplingSwizzle3D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_swizzle::string() << "is not supported."); #endif Texture3D texture; @@ -1183,9 +1183,9 @@ void TextureGLTest::samplingSwizzle3D() { #if defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) void TextureGLTest::samplingMaxLevel3D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::APPLE::texture_max_level::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::APPLE::texture_max_level::string() << "is not supported."); Texture3D texture; texture.setMaxLevel(750); @@ -1198,10 +1198,10 @@ void TextureGLTest::samplingMaxLevel3D() { void TextureGLTest::samplingBorderInteger3D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_integer::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_integer::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_border_clamp::string() << "is not supported."); #endif Texture3D a; @@ -1217,7 +1217,7 @@ void TextureGLTest::samplingBorderInteger3D() { void TextureGLTest::samplingDepthStencilMode3D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::stencil_texturing::string() << "is not supported."); #else if(!Context::current().isVersionSupported(Version::GLES310)) CORRADE_SKIP("OpenGL ES 3.1 is not supported."); @@ -1234,7 +1234,7 @@ void TextureGLTest::samplingDepthStencilMode3D() { void TextureGLTest::samplingBorder3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif if(!Context::current().isExtensionSupported() && @@ -1301,7 +1301,7 @@ void TextureGLTest::storage2D() { void TextureGLTest::storage3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif Texture3D texture; @@ -1454,7 +1454,7 @@ void TextureGLTest::subImage1DQuery() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture1D texture; texture.setStorage(1, TextureFormat::RGBA8, 4) @@ -1478,7 +1478,7 @@ void TextureGLTest::subImage1DQueryView() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture1D texture; texture.setStorage(1, TextureFormat::RGBA8, 4) @@ -1503,7 +1503,7 @@ void TextureGLTest::subImage1DQueryBuffer() { setTestCaseDescription(PixelStorage1DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture1D texture; texture.setStorage(1, TextureFormat::RGBA8, 4) @@ -1563,7 +1563,7 @@ void TextureGLTest::image2D() { #ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_WEBGL if(PixelStorage2DData[testCaseInstanceId()].storage != PixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() << "is not supported."); #else if(PixelStorage2DData[testCaseInstanceId()].storage != PixelStorage{}) CORRADE_SKIP("Image unpack is not supported in WebGL 1."); @@ -1671,7 +1671,7 @@ void TextureGLTest::subImage2D() { #ifdef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_WEBGL if(PixelStorage2DData[testCaseInstanceId()].storage != PixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() << "is not supported."); #else if(PixelStorage2DData[testCaseInstanceId()].storage != PixelStorage{}) CORRADE_SKIP("Image unpack is not supported in WebGL 1."); @@ -1738,7 +1738,7 @@ void TextureGLTest::subImage2DQuery() { setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1762,7 +1762,7 @@ void TextureGLTest::subImage2DQueryView() { setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1787,7 +1787,7 @@ void TextureGLTest::subImage2DQueryBuffer() { setTestCaseDescription(PixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{4}) @@ -1814,18 +1814,18 @@ void TextureGLTest::compressedImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif Texture2D texture; @@ -1857,18 +1857,18 @@ void TextureGLTest::compressedImage2DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif Texture2D texture; @@ -1901,10 +1901,10 @@ void TextureGLTest::compressedImage2DQueryView() { setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); Texture2D texture; texture.setCompressedImage(0, CompressedImageView2D{ @@ -1948,18 +1948,18 @@ void TextureGLTest::compressedSubImage2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif Texture2D texture; @@ -1992,18 +1992,18 @@ void TextureGLTest::compressedSubImage2DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::WEBGL::compressed_texture_s3tc::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ANGLE::texture_compression_dxt3::string() << "is not supported."); #endif #ifndef MAGNUM_TARGET_GLES if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #endif Texture2D texture; @@ -2038,13 +2038,13 @@ void TextureGLTest::compressedSubImage2DQuery() { setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 4}) @@ -2067,13 +2067,13 @@ void TextureGLTest::compressedSubImage2DQueryView() { setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 4}) @@ -2097,13 +2097,13 @@ void TextureGLTest::compressedSubImage2DQueryBuffer() { setTestCaseDescription(CompressedPixelStorage2DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage2DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture2D texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, {12, 4}) @@ -2130,9 +2130,9 @@ void TextureGLTest::image3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); if(PixelStorage3DData[testCaseInstanceId()].storage != PixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() << "is not supported."); #endif Texture3D texture; @@ -2244,9 +2244,9 @@ void TextureGLTest::subImage3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); if(PixelStorage3DData[testCaseInstanceId()].storage != PixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::unpack_subimage::string() << "is not supported."); #endif Texture3D texture; @@ -2306,7 +2306,7 @@ void TextureGLTest::subImage3DQuery() { setTestCaseDescription(PixelStorage3DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture3D texture; texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) @@ -2330,7 +2330,7 @@ void TextureGLTest::subImage3DQueryView() { setTestCaseDescription(PixelStorage3DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture3D texture; texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) @@ -2355,7 +2355,7 @@ void TextureGLTest::subImage3DQueryBuffer() { setTestCaseDescription(PixelStorage3DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); Texture3D texture; texture.setStorage(1, TextureFormat::RGBA8, Vector3i{4}) @@ -2385,12 +2385,12 @@ void TextureGLTest::compressedImage3D() { #else #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_bptc::string() << "is not supported."); #endif Texture3D texture; @@ -2425,12 +2425,12 @@ void TextureGLTest::compressedImage3DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_bptc::string() << "is not supported."); #endif Texture3D texture; @@ -2466,9 +2466,9 @@ void TextureGLTest::compressedImage3DQueryView() { setTestCaseDescription(CompressedPixelStorage3DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); Texture3D texture; texture.setCompressedImage(0, CompressedImageView3D{ @@ -2549,12 +2549,12 @@ void TextureGLTest::compressedSubImage3D() { #else #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_bptc::string() << "is not supported."); #endif Texture3D texture; @@ -2593,12 +2593,12 @@ void TextureGLTest::compressedSubImage3DBuffer() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::texture_compression_bptc::string() << "is not supported."); #endif Texture3D texture; @@ -2637,13 +2637,13 @@ void TextureGLTest::compressedSubImage3DQuery() { setTestCaseDescription(CompressedPixelStorage3DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture3D texture; texture.setStorage(1, TextureFormat::CompressedRGBABptcUnorm, {12, 4, 4}) @@ -2673,13 +2673,13 @@ void TextureGLTest::compressedSubImage3DQueryView() { setTestCaseDescription(CompressedPixelStorage3DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture3D texture; texture.setStorage(1, TextureFormat::CompressedRGBABptcUnorm, {12, 4, 4}) @@ -2710,13 +2710,13 @@ void TextureGLTest::compressedSubImage3DQueryBuffer() { setTestCaseDescription(CompressedPixelStorage3DData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::get_texture_sub_image::string() << "is not supported."); if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::texture_compression_bptc::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); if(CompressedPixelStorage3DData[testCaseInstanceId()].storage == CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::internalformat_query2::string() << "is not supported."); Texture3D texture; texture.setStorage(1, TextureFormat::CompressedRGBABptcUnorm, {12, 4, 4}) @@ -2748,7 +2748,7 @@ void TextureGLTest::compressedSubImage3DQueryBuffer() { #ifndef MAGNUM_TARGET_GLES void TextureGLTest::generateMipmap1D() { if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); Texture1D texture; texture.setImage(0, TextureFormat::RGBA8, @@ -2775,7 +2775,7 @@ void TextureGLTest::generateMipmap1D() { void TextureGLTest::generateMipmap2D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #endif Texture2D texture; @@ -2814,10 +2814,10 @@ void TextureGLTest::generateMipmap2D() { void TextureGLTest::generateMipmap3D() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::framebuffer_object::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif Texture3D texture; @@ -2876,7 +2876,7 @@ void TextureGLTest::invalidateImage2D() { void TextureGLTest::invalidateImage3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif Texture3D texture; @@ -2915,7 +2915,7 @@ void TextureGLTest::invalidateSubImage2D() { void TextureGLTest::invalidateSubImage3D() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::OES::texture_3D::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::OES::texture_3D::string() << "is not supported."); #endif Texture3D texture; @@ -2929,7 +2929,7 @@ void TextureGLTest::invalidateSubImage3D() { void TextureGLTest::srgbStorage() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::sRGB::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::sRGB::string() << "is not supported."); #endif Texture2D texture; @@ -2959,7 +2959,7 @@ void TextureGLTest::srgbStorage() { void TextureGLTest::srgbAlphaStorage() { #ifdef MAGNUM_TARGET_GLES2 if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::sRGB::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::EXT::sRGB::string() << "is not supported."); #endif Texture2D texture; diff --git a/src/Magnum/GL/Test/TimeQueryGLTest.cpp b/src/Magnum/GL/Test/TimeQueryGLTest.cpp index 9f1e48569..f3bef6b79 100644 --- a/src/Magnum/GL/Test/TimeQueryGLTest.cpp +++ b/src/Magnum/GL/Test/TimeQueryGLTest.cpp @@ -65,13 +65,13 @@ void TimeQueryGLTest::constructMove() { void TimeQueryGLTest::wrap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::timer_query::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::ARB::timer_query::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() << "is not supported."); #endif GLuint id; @@ -99,13 +99,13 @@ void TimeQueryGLTest::wrap() { void TimeQueryGLTest::queryTime() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::timer_query::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::ARB::timer_query::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() << "is not supported."); #endif Renderbuffer renderbuffer; @@ -144,13 +144,13 @@ void TimeQueryGLTest::queryTime() { void TimeQueryGLTest::queryTimestamp() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::timer_query::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::ARB::timer_query::string() << "is not supported."); #elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() << "is not supported."); #else if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available")); + CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() << "is not supported."); #endif Renderbuffer renderbuffer; diff --git a/src/Magnum/GL/Test/TransformFeedbackGLTest.cpp b/src/Magnum/GL/Test/TransformFeedbackGLTest.cpp index 2a80a86b4..d9be9ac8a 100644 --- a/src/Magnum/GL/Test/TransformFeedbackGLTest.cpp +++ b/src/Magnum/GL/Test/TransformFeedbackGLTest.cpp @@ -114,7 +114,7 @@ TransformFeedbackGLTest::TransformFeedbackGLTest() { void TransformFeedbackGLTest::construct() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif { @@ -130,7 +130,7 @@ void TransformFeedbackGLTest::construct() { void TransformFeedbackGLTest::constructMove() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif TransformFeedback a; @@ -160,7 +160,7 @@ void TransformFeedbackGLTest::constructMove() { void TransformFeedbackGLTest::wrap() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif GLuint id; @@ -182,7 +182,7 @@ void TransformFeedbackGLTest::label() { /* No-Op version is tested in AbstractObjectGLTest */ #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif if(!Context::current().isExtensionSupported() && !Context::current().isExtensionSupported()) @@ -263,7 +263,7 @@ XfbShader::XfbShader() { void TransformFeedbackGLTest::attachBase() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif /* Bind some FB to avoid errors on contexts w/o default FB */ @@ -310,7 +310,7 @@ void TransformFeedbackGLTest::attachBase() { void TransformFeedbackGLTest::attachRange() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif /* Bind some FB to avoid errors on contexts w/o default FB */ @@ -399,7 +399,7 @@ XfbMultiShader::XfbMultiShader() { void TransformFeedbackGLTest::attachBases() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif /* Bind some FB to avoid errors on contexts w/o default FB */ @@ -453,7 +453,7 @@ void TransformFeedbackGLTest::attachBases() { void TransformFeedbackGLTest::attachRanges() { #ifndef MAGNUM_TARGET_GLES if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); #endif /* Bind some FB to avoid errors on contexts w/o default FB */ @@ -511,7 +511,7 @@ void TransformFeedbackGLTest::attachRanges() { void TransformFeedbackGLTest::interleaved() { /* ARB_transform_feedback3 needed for gl_SkipComponents1 */ if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback3::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback3::string() << "is not supported."); /* Bind some FB to avoid errors on contexts w/o default FB */ Renderbuffer color; @@ -584,11 +584,11 @@ void TransformFeedbackGLTest::draw() { /* ARB_transform_feedback2 needed as base, other optional */ if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback2::string() << "is not supported."); if(DrawData[testCaseInstanceId()].stream && (!Context::current().isExtensionSupported() || TransformFeedback::maxVertexStreams() < 2)) CORRADE_SKIP(Extensions::ARB::transform_feedback3::string() + std::string(" is not supported well enough.")); if(DrawData[testCaseInstanceId()].instances && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::transform_feedback_instanced::string() + std::string(" is not supported.")); + CORRADE_SKIP(Extensions::ARB::transform_feedback_instanced::string() << "is not supported."); /* Bind some FB to avoid errors on contexts w/o default FB */ Renderbuffer color; diff --git a/src/Magnum/MeshTools/Test/CompileGLTest.cpp b/src/Magnum/MeshTools/Test/CompileGLTest.cpp index 639945bd7..ab7c939c0 100644 --- a/src/Magnum/MeshTools/Test/CompileGLTest.cpp +++ b/src/Magnum/MeshTools/Test/CompileGLTest.cpp @@ -380,7 +380,7 @@ template void CompileGLTest::twoDimensions() { #ifndef MAGNUM_TARGET_GLES if(data.flags & Flag::ObjectId && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif #ifdef MAGNUM_BUILD_DEPRECATED @@ -558,7 +558,7 @@ template void CompileGLTest::threeDimensions() { #ifndef MAGNUM_TARGET_GLES if(data.flags & Flag::ObjectId && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif #ifdef MAGNUM_BUILD_DEPRECATED @@ -852,10 +852,10 @@ template void CompileGLTest::threeDimensions() { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif _framebuffer.clear(GL::FramebufferClear::Color); diff --git a/src/Magnum/Shaders/Test/FlatGLTest.cpp b/src/Magnum/Shaders/Test/FlatGLTest.cpp index af5bbecdd..8cbfaad89 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -306,7 +306,7 @@ template void FlatGLTest::construct() { #ifndef MAGNUM_TARGET_GLES if((data.flags & Flat2D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif Flat shader{data.flags}; @@ -1045,7 +1045,7 @@ void FlatGLTest::renderObjectId2D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif CORRADE_COMPARE(_framebuffer.checkStatus(GL::FramebufferTarget::Draw), GL::Framebuffer::Status::Complete); @@ -1103,7 +1103,7 @@ void FlatGLTest::renderObjectId3D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif CORRADE_COMPARE(_framebuffer.checkStatus(GL::FramebufferTarget::Draw), GL::Framebuffer::Status::Complete); @@ -1166,7 +1166,7 @@ void FlatGLTest::renderObjectId3D() { void FlatGLTest::renderInstanced2D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!GL::Context::current().isExtensionSupported() && @@ -1175,7 +1175,7 @@ void FlatGLTest::renderInstanced2D() { CORRADE_SKIP("GL_{ANGLE,EXT,NV}_instanced_arrays is not supported"); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif @@ -1250,7 +1250,7 @@ void FlatGLTest::renderInstanced2D() { void FlatGLTest::renderInstanced3D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!GL::Context::current().isExtensionSupported() && @@ -1259,7 +1259,7 @@ void FlatGLTest::renderInstanced3D() { CORRADE_SKIP("GL_{ANGLE,EXT,NV}_instanced_arrays is not supported"); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp index bfd12dd50..6cab62742 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -544,7 +544,7 @@ void MeshVisualizerGLTest::construct2D() { #ifndef MAGNUM_TARGET_GLES if((data.flags & MeshVisualizer2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -586,7 +586,7 @@ void MeshVisualizerGLTest::construct3D() { #ifndef MAGNUM_TARGET_GLES if((data.flags & MeshVisualizer3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -626,10 +626,10 @@ void MeshVisualizerGLTest::construct3D() { void MeshVisualizerGLTest::constructWireframeGeometryShader2D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #ifdef MAGNUM_TARGET_GLES @@ -654,10 +654,10 @@ void MeshVisualizerGLTest::constructGeometryShader3D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #ifdef MAGNUM_TARGET_GLES @@ -713,10 +713,10 @@ void MeshVisualizerGLTest::construct3DGeometryShaderDisabledButNeeded() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif std::ostringstream out; @@ -733,10 +733,10 @@ void MeshVisualizerGLTest::construct3DConflictingBitangentInput() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif std::ostringstream out; @@ -900,10 +900,10 @@ void MeshVisualizerGLTest::setTangentBitangentNormalNotEnabled3D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif std::ostringstream out; @@ -961,10 +961,10 @@ void MeshVisualizerGLTest::renderTeardown() { void MeshVisualizerGLTest::renderDefaultsWireframe2D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #ifdef MAGNUM_TARGET_GLES @@ -1010,10 +1010,10 @@ void MeshVisualizerGLTest::renderDefaultsWireframe2D() { void MeshVisualizerGLTest::renderDefaultsWireframe3D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #ifdef MAGNUM_TARGET_GLES @@ -1064,7 +1064,7 @@ void MeshVisualizerGLTest::renderDefaultsObjectId2D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif /* Configure a texture with preset filtering and wrapping. The goal here is @@ -1113,7 +1113,7 @@ void MeshVisualizerGLTest::renderDefaultsObjectId3D() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif /* Configure a texture with preset filtering and wrapping. The goal here is @@ -1308,10 +1308,10 @@ void MeshVisualizerGLTest::renderDefaultsPrimitiveId3D() { void MeshVisualizerGLTest::renderDefaultsTangentBitangentNormal() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(4, 8, @@ -1347,10 +1347,10 @@ void MeshVisualizerGLTest::renderWireframe2D() { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #ifndef MAGNUM_TARGET_GLES if(!(data.flags & MeshVisualizer2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!(data.flags & MeshVisualizer2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #ifdef MAGNUM_TARGET_GLES @@ -1439,10 +1439,10 @@ void MeshVisualizerGLTest::renderWireframe3D() { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #ifndef MAGNUM_TARGET_GLES if(!(data.flags & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!(data.flags & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #ifdef MAGNUM_TARGET_GLES @@ -1539,7 +1539,7 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D() { #ifndef MAGNUM_TARGET_GLES if((data.flags2D & MeshVisualizer2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif /* Interestingly for PrimitiveIdFromVertexId gl_VertexID in SwiftShader @@ -1558,10 +1558,10 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D() { #ifndef MAGNUM_TARGET_GLES if(data.flags2D & MeshVisualizer2D::Flag::Wireframe && !(data.flags2D & MeshVisualizer2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(data.flags2D & MeshVisualizer2D::Flag::Wireframe && !(data.flags2D & MeshVisualizer2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #endif @@ -1639,7 +1639,7 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { #ifndef MAGNUM_TARGET_GLES if((data.flags3D & MeshVisualizer3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif /* Interestingly for PrimitiveIdFromVertexId gl_VertexID in SwiftShader @@ -1658,10 +1658,10 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { #ifndef MAGNUM_TARGET_GLES if(data.flags3D & MeshVisualizer3D::Flag::Wireframe && !(data.flags3D & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(data.flags3D & MeshVisualizer3D::Flag::Wireframe && !(data.flags3D & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #endif @@ -1746,10 +1746,10 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { void MeshVisualizerGLTest::renderWireframe3DPerspective() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif GL::Mesh plane = MeshTools::compile(Primitives::planeSolid()); @@ -1790,10 +1790,10 @@ void MeshVisualizerGLTest::renderTangentBitangentNormal() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif GL::Renderer::enable(GL::Renderer::Feature::DepthTest); diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index 1e074b21a..28da301c0 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -600,7 +600,7 @@ void PhongGLTest::construct() { #ifndef MAGNUM_TARGET_GLES if((data.flags & Phong::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif Phong shader{data.flags, data.lightCount}; @@ -1432,7 +1432,7 @@ void PhongGLTest::renderObjectId() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif CORRADE_COMPARE(_framebuffer.checkStatus(GL::FramebufferTarget::Draw), GL::Framebuffer::Status::Complete); @@ -1752,7 +1752,7 @@ void PhongGLTest::renderInstanced() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::instanced_arrays::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_WEBGL if(!GL::Context::current().isExtensionSupported() && @@ -1761,7 +1761,7 @@ void PhongGLTest::renderInstanced() { CORRADE_SKIP("GL_{ANGLE,EXT,NV}_instanced_arrays is not supported"); #else if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ANGLE::instanced_arrays::string() << "is not supported."); #endif #endif diff --git a/src/Magnum/Text/Test/RendererGLTest.cpp b/src/Magnum/Text/Test/RendererGLTest.cpp index aded2e1ac..f099cf627 100644 --- a/src/Magnum/Text/Test/RendererGLTest.cpp +++ b/src/Magnum/Text/Test/RendererGLTest.cpp @@ -263,7 +263,7 @@ void RendererGLTest::renderMeshIndexType() { void RendererGLTest::mutableText() { #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() + std::string(" is not supported")); + CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() << "is not supported."); #elif defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) if(!GL::Context::current().isExtensionSupported() && !GL::Context::current().isExtensionSupported()) diff --git a/src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp b/src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp index f04c40ca8..ad562fe7b 100644 --- a/src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp +++ b/src/Magnum/TextureTools/Test/DistanceFieldGLTest.cpp @@ -216,7 +216,7 @@ void DistanceFieldGLTest::test() { void DistanceFieldGLTest::benchmark() { #ifdef MAGNUM_TARGET_GLES if(!GL::Context::current().isExtensionSupported()) - CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query::string() + std::string{" is not supported, can't benchmark"}); + CORRADE_SKIP(GL::Extensions::EXT::disjoint_timer_query::string() << "is not supported, can't benchmark"); #endif Containers::Pointer importer; From aea8722729550ef8487d0ef5bc3cce72a3a959a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 5 Apr 2021 13:42:52 +0200 Subject: [PATCH 112/161] Add generic depth/stencil PixelFormat values. The 32-bit float depth be needed for the upcoming OpenEXR plugin, added also the remaining ones that will be eventually supported by KTX and DDS plugins. --- doc/changelog.dox | 8 ++ src/Magnum/DebugTools/CompareImage.cpp | 43 ++++++-- src/Magnum/DebugTools/CompareImage.h | 6 +- .../DebugTools/Test/CompareImageTest.cpp | 16 +++ .../GL/Implementation/pixelFormatMapping.hpp | 28 +++++ .../Implementation/pixelFormatMapping.hpp | 7 ++ src/Magnum/PixelFormat.cpp | 7 ++ src/Magnum/PixelFormat.h | 103 +++++++++++++++++- .../Vk/Implementation/pixelFormatMapping.hpp | 7 ++ 9 files changed, 214 insertions(+), 11 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index b94e6c63d..0e656a333 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -41,6 +41,14 @@ See also: @subsection changelog-latest-new New features - New @ref NoAllocate constructor tag, to be used by the @ref Vk library +- New @ref PixelFormat::Depth16Unorm, @relativeref{PixelFormat,Depth24Unorm}, + @relativeref{PixelFormat,Depth32F}, @relativeref{PixelFormat,Stencil8UI}, + @relativeref{PixelFormat,Depth16UnormStencil8UI}, + @relativeref{PixelFormat,Depth24UnormStencil8UI}, + @relativeref{PixelFormat,Depth32FStencil8UI} generic pixel formats, + including mapping to @ref GL::PixelFormat / @ref GL::PixelType, + @ref GL::TextureFormat and @ref Vk::PixelFormat and (partial) support in + @ref DebugTools::CompareImage @subsubsection changelog-latest-new-debugtools DebugTools library diff --git a/src/Magnum/DebugTools/CompareImage.cpp b/src/Magnum/DebugTools/CompareImage.cpp index ea0d30227..9a79fae4d 100644 --- a/src/Magnum/DebugTools/CompareImage.cpp +++ b/src/Magnum/DebugTools/CompareImage.cpp @@ -132,8 +132,17 @@ std::tuple, Float, Float> calculateImageDelta(const Pix Containers::arrayCast<2, const Math::Vector>(actualPixels), \ expected.pixels>(), delta); \ break; + #define _f(first, second, third, fourth, size, T) \ + case PixelFormat::first: \ + case PixelFormat::second: \ + case PixelFormat::third: \ + case PixelFormat::fourth: \ + max = calculateImageDelta( \ + Containers::arrayCast<2, const Math::Vector>(actualPixels), \ + expected.pixels>(), delta); \ + break; /* LCOV_EXCL_START */ - _e(R8Unorm, R8Srgb, R8UI, 1, UnsignedByte) + _f(R8Unorm, R8Srgb, R8UI, Stencil8UI, 1, UnsignedByte) _e(RG8Unorm, RG8Srgb, RG8UI, 2, UnsignedByte) _e(RGB8Unorm, RGB8Srgb, RGB8UI, 3, UnsignedByte) _e(RGBA8Unorm, RGBA8Srgb, RGBA8UI, 4, UnsignedByte) @@ -141,7 +150,7 @@ std::tuple, Float, Float> calculateImageDelta(const Pix _d(RG8Snorm, RG8I, 2, Byte) _d(RGB8Snorm, RGB8I, 3, Byte) _d(RGBA8Snorm, RGBA8I, 4, Byte) - _d(R16Unorm, R16UI, 1, UnsignedShort) + _e(R16Unorm, R16UI, Depth16Unorm, 1, UnsignedShort) _d(RG16Unorm, RG16UI, 2, UnsignedShort) _d(RGB16Unorm, RGB16UI, 3, UnsignedShort) _d(RGBA16Unorm, RGBA16UI, 4, UnsignedShort) @@ -149,7 +158,7 @@ std::tuple, Float, Float> calculateImageDelta(const Pix _d(RG16Snorm, RG16I, 2, Short) _d(RGB16Snorm, RGB16I, 3, Short) _d(RGBA16Snorm, RGBA16I, 4, Short) - _c(R32UI, 1, UnsignedInt) + _d(R32UI, Depth24Unorm, 1, UnsignedInt) _c(RG32UI, 2, UnsignedInt) _c(RGB32UI, 3, UnsignedInt) _c(RGBA32UI, 4, UnsignedInt) @@ -157,11 +166,12 @@ std::tuple, Float, Float> calculateImageDelta(const Pix _c(RG32I, 2, Int) _c(RGB32I, 3, Int) _c(RGBA32I, 4, Int) - _c(R32F, 1, Float) + _d(R32F, Depth32F, 1, Float) _c(RG32F, 2, Float) _c(RGB32F, 3, Float) _c(RGBA32F, 4, Float) /* LCOV_EXCL_STOP */ + #undef _f #undef _e #undef _d #undef _c @@ -171,6 +181,10 @@ std::tuple, Float, Float> calculateImageDelta(const Pix case PixelFormat::RGB16F: case PixelFormat::RGBA16F: CORRADE_ASSERT_UNREACHABLE("DebugTools::CompareImage: half-float formats are not supported yet", {}); + case PixelFormat::Depth16UnormStencil8UI: + case PixelFormat::Depth24UnormStencil8UI: + case PixelFormat::Depth32FStencil8UI: + CORRADE_ASSERT_UNREACHABLE("DebugTools::CompareImage: packed depth/stencil formats are not supported yet", {}); } #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -261,11 +275,18 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D& #define _e(first, second, third, size, T) \ case PixelFormat::first: \ case PixelFormat::second: \ - case PixelFormat::third: \ + case PixelFormat::third: \ + out << *reinterpret_cast*>(pixel); \ + break; + #define _f(first, second, third, fourth, size, T) \ + case PixelFormat::first: \ + case PixelFormat::second: \ + case PixelFormat::third: \ + case PixelFormat::fourth: \ out << *reinterpret_cast*>(pixel); \ break; /* LCOV_EXCL_START */ - _e(R8Unorm, R8Srgb, R8UI, 1, UnsignedByte) + _f(R8Unorm, R8Srgb, R8UI, Stencil8UI, 1, UnsignedByte) _e(RG8Unorm, RG8Srgb, RG8UI, 2, UnsignedByte) _c(RGB8UI, 3, UnsignedByte) _c(RGBA8UI, 4, UnsignedByte) @@ -274,7 +295,7 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D& _d(RG8Snorm, RG8I, 2, Byte) _d(RGB8Snorm, RGB8I, 3, Byte) _d(RGBA8Snorm, RGBA8I, 4, Byte) - _d(R16Unorm, R16UI, 1, UnsignedShort) + _e(R16Unorm, R16UI, Depth16Unorm, 1, UnsignedShort) _d(RG16Unorm, RG16UI, 2, UnsignedShort) _d(RGB16Unorm, RGB16UI, 3, UnsignedShort) _d(RGBA16Unorm, RGBA16UI, 4, UnsignedShort) @@ -282,7 +303,7 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D& _d(RG16Snorm, RG16I, 2, Short) _d(RGB16Snorm, RGB16I, 3, Short) _d(RGBA16Snorm, RGBA16I, 4, Short) - _c(R32UI, 1, UnsignedInt) + _d(R32UI, Depth24Unorm, 1, UnsignedInt) _c(RG32UI, 2, UnsignedInt) _c(RGB32UI, 3, UnsignedInt) _c(RGBA32UI, 4, UnsignedInt) @@ -290,11 +311,12 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D& _c(RG32I, 2, Int) _c(RGB32I, 3, Int) _c(RGBA32I, 4, Int) - _c(R32F, 1, Float) + _d(R32F, Depth32F, 1, Float) _c(RG32F, 2, Float) _c(RGB32F, 3, Float) _c(RGBA32F, 4, Float) /* LCOV_EXCL_STOP */ + #undef _f #undef _e #undef _d #undef _c @@ -313,6 +335,9 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D& case PixelFormat::RG16F: case PixelFormat::RGB16F: case PixelFormat::RGBA16F: + case PixelFormat::Depth16UnormStencil8UI: + case PixelFormat::Depth24UnormStencil8UI: + case PixelFormat::Depth32FStencil8UI: /* Already handled by a printing assert before */ CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } diff --git a/src/Magnum/DebugTools/CompareImage.h b/src/Magnum/DebugTools/CompareImage.h index 546d8e43c..690402944 100644 --- a/src/Magnum/DebugTools/CompareImage.h +++ b/src/Magnum/DebugTools/CompareImage.h @@ -227,7 +227,11 @@ Supports the following formats: - @ref PixelFormat::RGBA32F and its one-/two-/three-component versions @ref PixelFormat::RGBA16F and other half-float formats are not supported at the -moment. Implementation-specific pixel formats can't be supported. +moment. Packed depth/stencil formats are not supported at the moment, +however you can work around that by making separate depth/stencil pixel +views and @ref DebugTools-CompareImage-pixels "comparing those" to a +depth/stencil-only ground truth images. Implementation-specific pixel +formats can't be supported. Supports all @ref PixelStorage parameters. The images don't need to have the same pixel storage parameters, meaning you are able to compare different diff --git a/src/Magnum/DebugTools/Test/CompareImageTest.cpp b/src/Magnum/DebugTools/Test/CompareImageTest.cpp index e2809d700..29df8251a 100644 --- a/src/Magnum/DebugTools/Test/CompareImageTest.cpp +++ b/src/Magnum/DebugTools/Test/CompareImageTest.cpp @@ -54,6 +54,7 @@ struct CompareImageTest: TestSuite::Tester { void formatUnknown(); void formatHalf(); + void formatPackedDepthStencil(); void formatImplementationSpecific(); void calculateDelta(); @@ -125,6 +126,7 @@ struct CompareImageTest: TestSuite::Tester { CompareImageTest::CompareImageTest() { addTests({&CompareImageTest::formatUnknown, &CompareImageTest::formatHalf, + &CompareImageTest::formatPackedDepthStencil, &CompareImageTest::formatImplementationSpecific, &CompareImageTest::calculateDelta, @@ -265,6 +267,20 @@ void CompareImageTest::formatHalf() { CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: half-float formats are not supported yet\n"); } +void CompareImageTest::formatPackedDepthStencil() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + std::ostringstream out; + Error redirectError{&out}; + + ImageView2D image{PixelFormat::Depth24UnormStencil8UI, {}}; + Implementation::calculateImageDelta(image.format(), image.pixels(), image); + + CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: packed depth/stencil formats are not supported yet\n"); +} + void CompareImageTest::formatImplementationSpecific() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); diff --git a/src/Magnum/GL/Implementation/pixelFormatMapping.hpp b/src/Magnum/GL/Implementation/pixelFormatMapping.hpp index 0d487f6b4..8a0c14111 100644 --- a/src/Magnum/GL/Implementation/pixelFormatMapping.hpp +++ b/src/Magnum/GL/Implementation/pixelFormatMapping.hpp @@ -183,4 +183,32 @@ _n(RG32F, LuminanceAlpha, Float) _n(RGB32F, RGB, Float) _n(RGBA32F, RGBA, Float) #endif +#ifndef MAGNUM_TARGET_GLES2 +_c(Depth16Unorm, DepthComponent, UnsignedShort, DepthComponent16) +_c(Depth24Unorm, DepthComponent, UnsignedInt, DepthComponent24) +#else +_n(Depth16Unorm, DepthComponent, UnsignedShort) +_n(Depth24Unorm, DepthComponent, UnsignedInt) +#endif +#ifndef MAGNUM_TARGET_GLES2 +_c(Depth32F, DepthComponent, Float, DepthComponent32F) +#else +_s(Depth32F) +#endif +#ifndef MAGNUM_TARGET_WEBGL +_c(Stencil8UI, StencilIndex, UnsignedByte, StencilIndex8) +#else +_s(Stencil8UI) +#endif +_s(Depth16UnormStencil8UI) +#ifndef MAGNUM_TARGET_GLES2 +_c(Depth24UnormStencil8UI, DepthStencil, UnsignedInt248, Depth24Stencil8) +#else +_n(Depth24UnormStencil8UI, DepthStencil, UnsignedInt248) +#endif +#ifndef MAGNUM_TARGET_GLES2 +_c(Depth32FStencil8UI, DepthStencil, Float32UnsignedInt248Rev, Depth32FStencil8) +#else +_s(Depth32FStencil8UI) +#endif #endif diff --git a/src/Magnum/Implementation/pixelFormatMapping.hpp b/src/Magnum/Implementation/pixelFormatMapping.hpp index c9495f39e..67360a28f 100644 --- a/src/Magnum/Implementation/pixelFormatMapping.hpp +++ b/src/Magnum/Implementation/pixelFormatMapping.hpp @@ -77,4 +77,11 @@ _c(R32F) _c(RG32F) _c(RGB32F) _c(RGBA32F) +_c(Depth16Unorm) +_c(Depth24Unorm) +_c(Depth32F) +_c(Stencil8UI) +_c(Depth16UnormStencil8UI) +_c(Depth24UnormStencil8UI) +_c(Depth32FStencil8UI) #endif diff --git a/src/Magnum/PixelFormat.cpp b/src/Magnum/PixelFormat.cpp index 6aee8b921..3b38a15aa 100644 --- a/src/Magnum/PixelFormat.cpp +++ b/src/Magnum/PixelFormat.cpp @@ -48,6 +48,7 @@ UnsignedInt pixelSize(const PixelFormat format) { case PixelFormat::R8Srgb: case PixelFormat::R8UI: case PixelFormat::R8I: + case PixelFormat::Stencil8UI: return 1; case PixelFormat::RG8Unorm: case PixelFormat::RG8Snorm: @@ -59,6 +60,7 @@ UnsignedInt pixelSize(const PixelFormat format) { case PixelFormat::R16UI: case PixelFormat::R16I: case PixelFormat::R16F: + case PixelFormat::Depth16Unorm: return 2; case PixelFormat::RGB8Unorm: case PixelFormat::RGB8Snorm: @@ -79,6 +81,10 @@ UnsignedInt pixelSize(const PixelFormat format) { case PixelFormat::R32UI: case PixelFormat::R32I: case PixelFormat::R32F: + case PixelFormat::Depth24Unorm: + case PixelFormat::Depth32F: + case PixelFormat::Depth16UnormStencil8UI: + case PixelFormat::Depth24UnormStencil8UI: return 4; case PixelFormat::RGB16Unorm: case PixelFormat::RGB16Snorm: @@ -94,6 +100,7 @@ UnsignedInt pixelSize(const PixelFormat format) { case PixelFormat::RG32UI: case PixelFormat::RG32I: case PixelFormat::RG32F: + case PixelFormat::Depth32FStencil8UI: return 8; case PixelFormat::RGB32UI: case PixelFormat::RGB32I: diff --git a/src/Magnum/PixelFormat.h b/src/Magnum/PixelFormat.h index 50e0f468a..62bf70d67 100644 --- a/src/Magnum/PixelFormat.h +++ b/src/Magnum/PixelFormat.h @@ -663,7 +663,108 @@ enum class PixelFormat: UnsignedInt { * or @m_class{m-doc-external} [MTLPixelFormatRGBA32Float](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatrgba32float?language=objc). * @m_keywords{DXGI_FORMAT_R32G32B32A32_FLOAT MTLPixelFormatRGBA32Float} */ - RGBA32F + RGBA32F, + + /** + * 16-bit unsigned normalized depth. + * + * Corresponds to @ref GL::PixelFormat::DepthComponent and + * @ref GL::PixelType::UnsignedShort, + * @ref GL::TextureFormat::DepthComponent16; + * @ref Vk::PixelFormat::Depth16Unorm; + * @m_class{m-doc-external} [DXGI_FORMAT_D16_UNORM](https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format) + * or @m_class{m-doc-external} [MTLPixelFormatDepth16Unorm](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatdepth16unorm?language=objc). + * @m_keywords{DXGI_FORMAT_D16_UNORM MTLPixelFormatDepth16Unorm} + * @m_since_latest + */ + Depth16Unorm, + + /** + * 24-bit unsigned normalized depth. Data layout consistent with the + * [KTX2 specification](http://github.khronos.org/KTX-Specification/#_depth_and_stencil_formats) + * --- aligned to 32 bits with the 8 most significant bits unused. + * + * Corresponds to @ref GL::PixelFormat::DepthComponent and + * @ref GL::PixelType::UnsignedInt, + * @ref GL::TextureFormat::DepthComponent24; + * @ref Vk::PixelFormat::Depth24Unorm. No direct 24-bit D3D or Metal + * equivalent. + * @m_since_latest + * @todo wait, how GL interprets this? does it discard the top 8 bits? or + * should I use UnsignedInt248 instead? + */ + Depth24Unorm, + + /** + * 32-bit float depth. + * + * Corresponds to @ref GL::PixelFormat::DepthComponent and + * @ref GL::PixelType::Float, @ref GL::TextureFormat::DepthComponent32F; + * @ref Vk::PixelFormat::Depth32F; + * @m_class{m-doc-external} [DXGI_FORMAT_D32_FLOAT](https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format) + * or @m_class{m-doc-external} [MTLPixelFormatDepth32Float](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatdepth32float?language=objc). + * @m_keywords{DXGI_FORMAT_D32_FLOAT MTLPixelFormatDepth32Float} + * @m_since_latest + */ + Depth32F, + + /** + * 8-bit unsigned integral stencil. + * + * Corresponds to @ref GL::PixelFormat::StencilIndex and + * @ref GL::PixelType::UnsignedByte, @ref GL::TextureFormat::StencilIndex8; + * @ref Vk::PixelFormat::Stencil8UI + * or @m_class{m-doc-external} [MTLPixelFormatStencil8](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatstencil8?language=objc). No direct 8-bit D3D equivalent. + * @m_keywords{MTLPixelFormatStencil8} + * @m_since_latest + */ + Stencil8UI, + + /** + * 16-bit unsigned normalized depth with 8-bit unsigned integral stencil. + * Data layout consistent with the [KTX2 specification](http://github.khronos.org/KTX-Specification/#_depth_and_stencil_formats) + * --- aligned to 32 bits with depth in the 16 least significant bits and + * the 8 most significant bits unused. + * + * Corresponds to @ref Vk::PixelFormat::Depth16UnormStencil8UI. No direct + * 32-bit GL, D3D or Metal equivalent. + * @m_since_latest + */ + Depth16UnormStencil8UI, + + /** + * 24-bit unsigned normalized depth with 8-bit unsigned integral stencil. + * Data layout consistent with the [KTX2 specification](http://github.khronos.org/KTX-Specification/#_depth_and_stencil_formats) + * --- packed to 32 bits with depth in the 24 least significant bits + * and stencil being in the 8 most significant bits. + * + * Corresponds to @ref GL::PixelFormat::DepthStencil and + * @ref GL::PixelType::UnsignedInt248, + * @ref GL::TextureFormat::Depth24Stencil8; + * @ref Vk::PixelFormat::Depth24UnormStencil8UI; + * @m_class{m-doc-external} [DXGI_FORMAT_D24_UNORM_S8_UINT](https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format) + * or @m_class{m-doc-external} [MTLPixelFormatDepth24Unorm_Stencil8](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatdepth24unorm_stencil8?language=objc). + * @m_keywords{DXGI_FORMAT_D24_UNORM_S8_UINT MTLPixelFormatDepth24Unorm_Stencil8} + * @m_since_latest + */ + Depth24UnormStencil8UI, + + /** + * 32-bit float depth with 8-bit unsigned integral stencil. Data layout + * consistent with the [KTX2 specification](http://github.khronos.org/KTX-Specification/#_depth_and_stencil_formats) + * --- packed to 64 bits with the depth in the 32 least significant + * bits and the 24 most significant bits unused. + * + * Corresponds to @ref GL::PixelFormat::DepthStencil and + * @ref GL::PixelType::Float32UnsignedInt248Rev, + * @ref GL::TextureFormat::Depth32FStencil8; + * @ref Vk::PixelFormat::Depth32FStencil8UI; + * @m_class{m-doc-external} [DXGI_FORMAT_D32_FLOAT_S8X24_UINT](https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format) + * or @m_class{m-doc-external} [MTLPixelFormatDepth32Float_Stencil8](https://developer.apple.com/documentation/metal/mtlpixelformat/mtlpixelformatdepth32float_stencil8?language=objc). + * @m_keywords{DXGI_FORMAT_D32_FLOAT_S8X24_UINT MTLPixelFormatDepth32Float_Stencil8} + * @m_since_latest + */ + Depth32FStencil8UI }; /** diff --git a/src/Magnum/Vk/Implementation/pixelFormatMapping.hpp b/src/Magnum/Vk/Implementation/pixelFormatMapping.hpp index 9e2d7986d..51a7e490c 100644 --- a/src/Magnum/Vk/Implementation/pixelFormatMapping.hpp +++ b/src/Magnum/Vk/Implementation/pixelFormatMapping.hpp @@ -77,4 +77,11 @@ _c(R32F) _c(RG32F) _c(RGB32F) _c(RGBA32F) +_c(Depth16Unorm) +_c(Depth24Unorm) +_c(Depth32F) +_c(Stencil8UI) +_c(Depth16UnormStencil8UI) +_c(Depth24UnormStencil8UI) +_c(Depth32FStencil8UI) #endif From 1a0a96612f88413ccfaf2dc1ad90d687ffb217e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 5 Apr 2021 13:43:54 +0200 Subject: [PATCH 113/161] VK: doc++ --- src/Magnum/Vk/Device.h | 4 +++- src/Magnum/Vk/Shader.h | 2 ++ src/Magnum/Vk/ShaderSet.h | 10 +++++----- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Magnum/Vk/Device.h b/src/Magnum/Vk/Device.h index 84b4f8c45..8289e8621 100644 --- a/src/Magnum/Vk/Device.h +++ b/src/Magnum/Vk/Device.h @@ -114,7 +114,9 @@ explicitly enabled. @snippet MagnumVk.cpp Device-creation-check-supported With both @ref Instance and @ref Device created, you can proceed to setting up -a @ref CommandPool. +a @ref CommandPool and a @ref Pipeline, which will then need a +@ref ShaderSet and a @ref PipelineLayout. For rasterization pipelines, you'll +additionally need a @ref MeshLayout and a @ref RenderPass. @subsection Vk-Device-portability-subset Vulkan portability subset diff --git a/src/Magnum/Vk/Shader.h b/src/Magnum/Vk/Shader.h index 100ae29f3..1e89c555a 100644 --- a/src/Magnum/Vk/Shader.h +++ b/src/Magnum/Vk/Shader.h @@ -142,6 +142,8 @@ keeping a loaded file in scope until it's consumed by the @ref Shader constructor: @snippet MagnumVk.cpp Shader-creation + +@see @ref CORRADE_INTERNAL_ASSERT_EXPRESSION() */ class MAGNUM_VK_EXPORT Shader { public: diff --git a/src/Magnum/Vk/ShaderSet.h b/src/Magnum/Vk/ShaderSet.h index 941490aa5..c47a2af6d 100644 --- a/src/Magnum/Vk/ShaderSet.h +++ b/src/Magnum/Vk/ShaderSet.h @@ -110,11 +110,11 @@ pipeline. @section Vk-ShaderSet-usage Usage Based on whether the shader set is for a rasterization, compute or ray tracing -pipeline, you'll call @ref addShader() with all stages that the pipeline needs. -At the very least you need to specify what stage is the shader for and the -entrypoint name --- usually it'd be @cpp main() @ce, but there can be also -SPIR-V shader modules with multiple entry points, which is why this parameter -is needed. +pipeline, you'll call @ref addShader() with all @ref Shader stages that the +pipeline needs. At the very least you need to specify what stage is the shader +for and the entrypoint name --- usually it'd be @cpp main() @ce, but there can +be also SPIR-V shader modules with multiple entry points, which is why this +parameter is needed. @snippet MagnumVk.cpp ShaderSet-usage From 84dcd52625172f15df61a0e4f6c53f2b216edd18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 5 Apr 2021 17:29:57 +0200 Subject: [PATCH 114/161] DebugTools: doc++ --- doc/snippets/debugtools-compareimage.cpp | 17 ++++++++++++----- src/Magnum/DebugTools/CompareImage.h | 18 +++++++++++++++--- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/doc/snippets/debugtools-compareimage.cpp b/doc/snippets/debugtools-compareimage.cpp index 2650aa18f..8dd0df16b 100644 --- a/doc/snippets/debugtools-compareimage.cpp +++ b/doc/snippets/debugtools-compareimage.cpp @@ -38,6 +38,8 @@ using namespace Magnum; +#define DOXYGEN_IGNORE(...) __VA_ARGS__ + namespace { Image2D doProcessing() { @@ -68,17 +70,22 @@ struct ProcessingTest: TestSuite::Tester { ProcessingTest::ProcessingTest() { addTests({&ProcessingTest::process}); + + if(false) { +/* [basic] */ +Image2D actual{DOXYGEN_IGNORE(doProcessing())}, expected{DOXYGEN_IGNORE(loadExpectedImage())}; +CORRADE_COMPARE_AS(actual, expected, DebugTools::CompareImage); +/* [basic] */ + } } -/** [0] */ void ProcessingTest::process() { Image2D actual = doProcessing(); Image2D expected = loadExpectedImage(); - - CORRADE_COMPARE_WITH(actual, expected, - (DebugTools::CompareImage{170.0f, 96.0f})); +/* [delta] */ +CORRADE_COMPARE_WITH(actual, expected, (DebugTools::CompareImage{170.0f, 96.0f})); +/* [delta] */ } -/** [0] */ CORRADE_TEST_MAIN(ProcessingTest) diff --git a/src/Magnum/DebugTools/CompareImage.h b/src/Magnum/DebugTools/CompareImage.h index 690402944..489c19fa7 100644 --- a/src/Magnum/DebugTools/CompareImage.h +++ b/src/Magnum/DebugTools/CompareImage.h @@ -200,15 +200,27 @@ template struct ComparatorTraits Date: Mon, 5 Apr 2021 18:21:19 +0200 Subject: [PATCH 115/161] DebugTools: support half-float formats in CompareImage. --- doc/changelog.dox | 5 ++ src/Magnum/DebugTools/CompareImage.cpp | 18 +++---- src/Magnum/DebugTools/CompareImage.h | 12 ++--- .../DebugTools/Test/CompareImageTest.cpp | 53 +++++++++++++------ 4 files changed, 56 insertions(+), 32 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 0e656a333..ba9d293a0 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -209,6 +209,11 @@ See also: @subsection changelog-latest-changes Changes and improvements +@subsubsection changelog-latest-changes-debugtools DebugTools library + +- @ref DebugTools::CompareImage now supports comparing half-float pixel + formats as well + @subsubsection changelog-latest-changes-gl GL library - The @ref GL::Context class got significantly optimized in terms of compile diff --git a/src/Magnum/DebugTools/CompareImage.cpp b/src/Magnum/DebugTools/CompareImage.cpp index 9a79fae4d..73a37e779 100644 --- a/src/Magnum/DebugTools/CompareImage.cpp +++ b/src/Magnum/DebugTools/CompareImage.cpp @@ -38,6 +38,7 @@ #include "Magnum/ImageView.h" #include "Magnum/PixelFormat.h" #include "Magnum/Math/Functions.h" +#include "Magnum/Math/Half.h" #include "Magnum/Math/Color.h" #include "Magnum/Math/Algorithms/KahanSum.h" #include "Magnum/Trade/AbstractImageConverter.h" @@ -166,6 +167,10 @@ std::tuple, Float, Float> calculateImageDelta(const Pix _c(RG32I, 2, Int) _c(RGB32I, 3, Int) _c(RGBA32I, 4, Int) + _c(R16F, 1, Half) + _c(RG16F, 2, Half) + _c(RGB16F, 3, Half) + _c(RGBA16F, 4, Half) _d(R32F, Depth32F, 1, Float) _c(RG32F, 2, Float) _c(RGB32F, 3, Float) @@ -176,11 +181,6 @@ std::tuple, Float, Float> calculateImageDelta(const Pix #undef _d #undef _c - case PixelFormat::R16F: - case PixelFormat::RG16F: - case PixelFormat::RGB16F: - case PixelFormat::RGBA16F: - CORRADE_ASSERT_UNREACHABLE("DebugTools::CompareImage: half-float formats are not supported yet", {}); case PixelFormat::Depth16UnormStencil8UI: case PixelFormat::Depth24UnormStencil8UI: case PixelFormat::Depth32FStencil8UI: @@ -311,6 +311,10 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D& _c(RG32I, 2, Int) _c(RGB32I, 3, Int) _c(RGBA32I, 4, Int) + _c(R16F, 1, Half) + _c(RG16F, 2, Half) + _c(RGB16F, 3, Half) + _c(RGBA16F, 4, Half) _d(R32F, Depth32F, 1, Float) _c(RG32F, 2, Float) _c(RGB32F, 3, Float) @@ -331,10 +335,6 @@ void printPixelAt(Debug& out, const Containers::StridedArrayView3D& out << *reinterpret_cast(pixel); break; - case PixelFormat::R16F: - case PixelFormat::RG16F: - case PixelFormat::RGB16F: - case PixelFormat::RGBA16F: case PixelFormat::Depth16UnormStencil8UI: case PixelFormat::Depth24UnormStencil8UI: case PixelFormat::Depth32FStencil8UI: diff --git a/src/Magnum/DebugTools/CompareImage.h b/src/Magnum/DebugTools/CompareImage.h index 489c19fa7..3bc9c71f2 100644 --- a/src/Magnum/DebugTools/CompareImage.h +++ b/src/Magnum/DebugTools/CompareImage.h @@ -236,14 +236,14 @@ Supports the following formats: @ref PixelFormat::RGBA32UI and their one-/two-/three-component versions - @ref PixelFormat::RGBA8I, @ref PixelFormat::RGBA16I, @ref PixelFormat::RGBA32I and their one-/two-/three-component versions +- @ref PixelFormat::RGBA16F and its one-/two-/three-component versions - @ref PixelFormat::RGBA32F and its one-/two-/three-component versions -@ref PixelFormat::RGBA16F and other half-float formats are not supported at the -moment. Packed depth/stencil formats are not supported at the moment, -however you can work around that by making separate depth/stencil pixel -views and @ref DebugTools-CompareImage-pixels "comparing those" to a -depth/stencil-only ground truth images. Implementation-specific pixel -formats can't be supported. +Packed depth/stencil formats are not supported at the moment, however you can +work around that by making separate depth/stencil pixel views and +@ref DebugTools-CompareImage-pixels "comparing the views" to a +depth/stencil-only ground truth images. Implementation-specific pixel formats +can't be supported. Supports all @ref PixelStorage parameters. The images don't need to have the same pixel storage parameters, meaning you are able to compare different diff --git a/src/Magnum/DebugTools/Test/CompareImageTest.cpp b/src/Magnum/DebugTools/Test/CompareImageTest.cpp index 29df8251a..ceaee77fc 100644 --- a/src/Magnum/DebugTools/Test/CompareImageTest.cpp +++ b/src/Magnum/DebugTools/Test/CompareImageTest.cpp @@ -40,8 +40,9 @@ #include "Magnum/ImageView.h" #include "Magnum/PixelFormat.h" #include "Magnum/DebugTools/CompareImage.h" -#include "Magnum/Math/Functions.h" #include "Magnum/Math/Color.h" +#include "Magnum/Math/Functions.h" +#include "Magnum/Math/Half.h" #include "Magnum/Trade/AbstractImageConverter.h" #include "Magnum/Trade/AbstractImporter.h" @@ -53,7 +54,6 @@ struct CompareImageTest: TestSuite::Tester { explicit CompareImageTest(); void formatUnknown(); - void formatHalf(); void formatPackedDepthStencil(); void formatImplementationSpecific(); @@ -70,6 +70,7 @@ struct CompareImageTest: TestSuite::Tester { void pixelDelta(); void pixelDeltaEmpty(); void pixelDeltaOverflow(); + void pixelDeltaHalf(); void pixelDeltaSpecials(); void compareDifferentSize(); @@ -125,7 +126,6 @@ struct CompareImageTest: TestSuite::Tester { CompareImageTest::CompareImageTest() { addTests({&CompareImageTest::formatUnknown, - &CompareImageTest::formatHalf, &CompareImageTest::formatPackedDepthStencil, &CompareImageTest::formatImplementationSpecific, @@ -142,6 +142,7 @@ CompareImageTest::CompareImageTest() { &CompareImageTest::pixelDelta, &CompareImageTest::pixelDeltaEmpty, &CompareImageTest::pixelDeltaOverflow, + &CompareImageTest::pixelDeltaHalf, &CompareImageTest::pixelDeltaSpecials, &CompareImageTest::compareDifferentSize, @@ -218,6 +219,8 @@ CompareImageTest::CompareImageTest() { setupExternalPluginManager() function */ } +using namespace Math::Literals; + const Float ActualRedData[] = { 0.3f, 1.0f, 0.9f, 0.9f, 0.6f, 0.2f, @@ -253,20 +256,6 @@ void CompareImageTest::formatUnknown() { CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: unknown format PixelFormat(0xdead)\n"); } -void CompareImageTest::formatHalf() { - #ifdef CORRADE_NO_ASSERT - CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); - #endif - - std::ostringstream out; - Error redirectError{&out}; - - ImageView2D image{PixelFormat::RG16F, {}}; - Implementation::calculateImageDelta(image.format(), image.pixels(), image); - - CORRADE_COMPARE(out.str(), "DebugTools::CompareImage: half-float formats are not supported yet\n"); -} - void CompareImageTest::formatPackedDepthStencil() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -532,6 +521,36 @@ void CompareImageTest::pixelDeltaOverflow() { " [2,0] Vector(0.9), expected Vector(0.6) (Δ = 0.3)"); } +const Vector2h ActualHalfData[]{ + {0.3_h, 1.0_h}, { 0.9_h, 0.9_h}, + {0.6_h, 0.2_h}, {-0.1_h, 1.0_h}, +}; + +const Vector2h ExpectedHalfData[]{ + {0.65_h, 1.0_h}, {0.6_h, 0.91_h}, + {0.6_h, 0.1_h}, {0.02_h, 0.0_h} +}; + +const Float DeltaHalf[] { + 0.35f/2.0f, 0.31f/2.0f, + 0.01f/2.0f, 0.22f/2.0f +}; + +const ImageView2D ActualHalf{PixelFormat::RG16F, {2, 2}, ActualHalfData}; +const ImageView2D ExpectedHalf{PixelFormat::RG16F, {2, 2}, ExpectedHalfData}; + +void CompareImageTest::pixelDeltaHalf() { + std::ostringstream out; + Debug d{&out, Debug::Flag::DisableColors}; + Implementation::printPixelDeltas(d, DeltaHalf, ActualHalf.format(), ActualHalf.pixels(), ExpectedHalf.pixels(), 0.5f, 0.1f, 10); + + CORRADE_COMPARE(out.str(), "\n" + " Pixels above max/mean threshold:\n" + " [0,0] Vector(0.3, 1), expected Vector(0.6499, 1) (Δ = 0.175)\n" + " [1,0] Vector(0.8999, 0.8999), expected Vector(0.6001, 0.9102) (Δ = 0.155)\n" + " [1,1] Vector(-0.09998, 1), expected Vector(0.02, 0) (Δ = 0.11)"); +} + void CompareImageTest::pixelDeltaSpecials() { std::ostringstream out; Debug d{&out, Debug::Flag::DisableColors}; From 41bea89c04bb56706eaefc3023a8c9e154085fdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 5 Apr 2021 18:30:40 +0200 Subject: [PATCH 116/161] DebugTools: restore usage of external plugins in the CompareImage test. This was working originally, but got broken when all plugin interfaces got switched to look for plugins next to the library and not in a hardcoded install path. --- src/Magnum/DebugTools/Test/CompareImageTest.cpp | 8 ++++---- src/Magnum/DebugTools/Test/configure.h.cmake | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Magnum/DebugTools/Test/CompareImageTest.cpp b/src/Magnum/DebugTools/Test/CompareImageTest.cpp index ceaee77fc..82600d78c 100644 --- a/src/Magnum/DebugTools/Test/CompareImageTest.cpp +++ b/src/Magnum/DebugTools/Test/CompareImageTest.cpp @@ -1190,7 +1190,7 @@ void CompareImageTest::imageFileExpectedLoadFailed() { } void CompareImageTest::imageFileActualIsCompressed() { - PluginManager::Manager manager; + PluginManager::Manager manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded || manager.load("DdsImporter") < PluginManager::LoadState::Loaded) CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded."); @@ -1213,7 +1213,7 @@ void CompareImageTest::imageFileActualIsCompressed() { } void CompareImageTest::imageFileExpectedIsCompressed() { - PluginManager::Manager manager; + PluginManager::Manager manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded || manager.load("DdsImporter") < PluginManager::LoadState::Loaded) CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded."); @@ -1389,7 +1389,7 @@ void CompareImageTest::imageToFileExpectedLoadFailed() { } void CompareImageTest::imageToFileExpectedIsCompressed() { - PluginManager::Manager manager; + PluginManager::Manager manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded || manager.load("DdsImporter") < PluginManager::LoadState::Loaded) CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded."); @@ -1528,7 +1528,7 @@ void CompareImageTest::fileToImageActualLoadFailed() { } void CompareImageTest::fileToImageActualIsCompressed() { - PluginManager::Manager manager; + PluginManager::Manager manager{MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR}; if(manager.load("AnyImageImporter") < PluginManager::LoadState::Loaded || manager.load("DdsImporter") < PluginManager::LoadState::Loaded) CORRADE_SKIP("AnyImageImporter or DdsImporter plugins can't be loaded."); diff --git a/src/Magnum/DebugTools/Test/configure.h.cmake b/src/Magnum/DebugTools/Test/configure.h.cmake index c00bf210c..fce94fc31 100644 --- a/src/Magnum/DebugTools/Test/configure.h.cmake +++ b/src/Magnum/DebugTools/Test/configure.h.cmake @@ -30,3 +30,17 @@ #define DEBUGTOOLS_TEST_DIR "${DEBUGTOOLS_TEST_DIR}" #define SCREENSHOTTEST_SAVE_DIR "${SCREENSHOTTEST_SAVE_DIR}" #define COMPAREIMAGETEST_SAVE_DIR "${COMPAREIMAGETEST_SAVE_DIR}" + +#ifdef CORRADE_TARGET_WINDOWS +#ifdef CORRADE_IS_DEBUG_BUILD +#define MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_IMPORTER_DEBUG_BINARY_INSTALL_DIR}" +#else +#define MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_IMPORTER_RELEASE_BINARY_INSTALL_DIR}" +#endif +#else +#ifdef CORRADE_IS_DEBUG_BUILD +#define MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_IMPORTER_DEBUG_LIBRARY_INSTALL_DIR}" +#else +#define MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${MAGNUM_PLUGINS_IMPORTER_RELEASE_LIBRARY_INSTALL_DIR}" +#endif +#endif From 069c1e6ceebde89fdcea928ca105e8bc87911d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 7 Apr 2021 17:31:37 +0200 Subject: [PATCH 117/161] doc: add OpenEXR import/export to the file format tables. And mark MiniExrImageConverter as having severe limitations, since that's what it is. (Originally I actually thought EXR supports just half-floats and RGB/RGBA but that's far from being the case!) --- doc/file-formats.dox | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/doc/file-formats.dox b/doc/file-formats.dox index 2c1e74482..a50807b42 100644 --- a/doc/file-formats.dox +++ b/doc/file-formats.dox @@ -107,6 +107,22 @@ Together with @ref file-formats-scene-importers "scene importers" derived from + +OpenEXR (`*.exr`) +`OpenExrImporter` +@ref Trade::OpenExrImporter "OpenExrImporter" +@ref Trade-OpenExrImporter-behavior "some" +external, tiny +BSD 3-clause + + +@ref Trade::DevIlImageImporter "DevIlImageImporter" +@ref Trade-DevIlImageImporter-behavior-exr "severe" +external +LGPLv2.1 + + + GIF
(`*.gif`) `GifImporter` @@ -284,10 +300,16 @@ Derived from @ref Trade::AbstractImageConverter. -OpenEXR (`*.exr`) -`OpenExrImageConverter` +OpenEXR (`*.exr`) +`OpenExrImageConverter` +@ref Trade::OpenExrImageConverter "OpenExrImageConverter" +@ref Trade-OpenExrImageConverter-behavior "some" +external, tiny +BSD 3-clause + + @ref Trade::MiniExrImageConverter "MiniExrImageConverter" -@ref Trade-MiniExrImageConverter-behavior "minor" +@ref Trade-MiniExrImageConverter-behavior "severe" bundled public domain From bd273d7bcefc85c527a86cb105b5dc4daebd1c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 7 Apr 2021 17:33:07 +0200 Subject: [PATCH 118/161] doc: force a bit better table formatting. --- doc/file-formats.dox | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/file-formats.dox b/doc/file-formats.dox index a50807b42..40980c65b 100644 --- a/doc/file-formats.dox +++ b/doc/file-formats.dox @@ -81,7 +81,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from @ref Trade::StbImageImporter "StbImageImporter" @ref Trade-StbImageImporter-behavior-bmp "minor" bundled -public domain +public domain @ref Trade::DevIlImageImporter "DevIlImageImporter" @@ -129,7 +129,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from @ref Trade::StbImageImporter "StbImageImporter" @ref Trade-StbImageImporter-behavior-animated-gifs "minor" bundled -public domain +public domain @ref Trade::DevIlImageImporter "DevIlImageImporter" @@ -145,7 +145,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from @ref Trade::StbImageImporter "StbImageImporter" @m_span{m-text m-dim} none @m_endspan bundled -public domain +public domain @ref Trade::DevIlImageImporter "DevIlImageImporter" @@ -183,7 +183,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from @ref Trade::StbImageImporter "StbImageImporter" @ref Trade-StbImageImporter-behavior-arithmetic-jpeg "some" bundled -public domain +public domain @ref Trade::DevIlImageImporter "DevIlImageImporter" @@ -205,7 +205,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from @ref Trade::StbImageImporter "StbImageImporter" @m_span{m-text m-dim} none @m_endspan bundled -public domain +public domain @ref Trade::DevIlImageImporter "DevIlImageImporter" @@ -221,7 +221,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from @ref Trade::StbImageImporter "StbImageImporter" @ref Trade-StbImageImporter-behavior-psd "severe" bundled -public domain +public domain @ref Trade::DevIlImageImporter "DevIlImageImporter" @@ -243,7 +243,7 @@ Together with @ref file-formats-scene-importers "scene importers" derived from @ref Trade::StbImageImporter "StbImageImporter" @m_span{m-text m-dim} none @m_endspan bundled -public domain +public domain @ref Trade::DevIlImageImporter "DevIlImageImporter" @@ -295,7 +295,7 @@ Derived from @ref Trade::AbstractImageConverter. @ref Trade::StbImageConverter "StbImageConverter" unknown bundled -public domain +public domain @@ -311,7 +311,7 @@ Derived from @ref Trade::AbstractImageConverter. @ref Trade::MiniExrImageConverter "MiniExrImageConverter" @ref Trade-MiniExrImageConverter-behavior "severe" bundled -public domain +public domain @@ -321,7 +321,7 @@ Derived from @ref Trade::AbstractImageConverter. @ref Trade::StbImageConverter "StbImageConverter" @m_span{m-text m-dim} none @m_endspan bundled -public domain +public domain @@ -337,7 +337,7 @@ Derived from @ref Trade::AbstractImageConverter. @ref Trade::StbImageConverter "StbImageConverter" @ref Trade-StbImageConverter-behavior-arithmetic-jpeg "minor" bundled -public domain +public domain @@ -353,7 +353,7 @@ Derived from @ref Trade::AbstractImageConverter. @ref Trade::StbImageConverter "StbImageConverter" @ref Trade-StbImageConverter-behavior-16bit-png "some" bundled -public domain +public domain @@ -369,7 +369,7 @@ Derived from @ref Trade::AbstractImageConverter. @ref Trade::StbImageConverter "StbImageConverter" @m_span{m-text m-dim} none @m_endspan bundled -public domain +public domain From d523ab71249725e60c48543fbda9c9a44e42b6df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 12:09:25 +0200 Subject: [PATCH 119/161] ShaderTools: less confusing function parameter names. --- src/Magnum/ShaderTools/AbstractConverter.cpp | 90 +++++++++---------- src/Magnum/ShaderTools/AbstractConverter.h | 20 ++--- .../AnyShaderConverter/AnyConverter.cpp | 6 +- .../AnyShaderConverter/AnyConverter.h | 2 +- 4 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/Magnum/ShaderTools/AbstractConverter.cpp b/src/Magnum/ShaderTools/AbstractConverter.cpp index e43a4ee79..98c35db2a 100644 --- a/src/Magnum/ShaderTools/AbstractConverter.cpp +++ b/src/Magnum/ShaderTools/AbstractConverter.cpp @@ -268,7 +268,7 @@ Containers::Array AbstractConverter::doConvertDataToData(Stage, Containers CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::convertDataToData(): feature advertised but not implemented", {}); } -bool AbstractConverter::convertDataToFile(const Stage stage, const Containers::ArrayView data, const Containers::StringView to) { +bool AbstractConverter::convertDataToFile(const Stage stage, const Containers::ArrayView data, const Containers::StringView filename) { CORRADE_ASSERT(features() >= ConverterFeature::ConvertData, "ShaderTools::AbstractConverter::convertDataToFile(): feature not supported", {}); @@ -278,22 +278,22 @@ bool AbstractConverter::convertDataToFile(const Stage stage, const Containers::A Containers::Array out = doConvertDataToData(stage, Containers::arrayCast(data)); if(!out) return false; - if(!Utility::Directory::write(to, out)) { - Error{} << "ShaderTools::AbstractConverter::convertDataToFile(): cannot write to file" << to; + if(!Utility::Directory::write(filename, out)) { + Error{} << "ShaderTools::AbstractConverter::convertDataToFile(): cannot write to file" << filename; return false; } return true; } -Containers::Array AbstractConverter::convertDataToDataUsingInputFileCallbacks(const char* const prefix, const Stage stage, const Containers::StringView from) { - const Containers::Optional> data = _inputFileCallback(from, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData); +Containers::Array AbstractConverter::convertDataToDataUsingInputFileCallbacks(const char* const prefix, const Stage stage, const Containers::StringView filename) { + const Containers::Optional> data = _inputFileCallback(filename, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData); if(!data) { - Error{} << prefix << "cannot open file" << from; + Error{} << prefix << "cannot open file" << filename; return {}; } Containers::Array out = doConvertDataToData(stage, *data); - _inputFileCallback(from, InputFileCallbackPolicy::Close, _inputFileCallbackUserData); + _inputFileCallback(filename, InputFileCallbackPolicy::Close, _inputFileCallbackUserData); return out; } @@ -367,7 +367,7 @@ bool AbstractConverter::doConvertFileToFile(const Stage stage, const Containers: return true; } -Containers::Array AbstractConverter::convertFileToData(const Stage stage, const Containers::StringView from) { +Containers::Array AbstractConverter::convertFileToData(const Stage stage, const Containers::StringView filename) { CORRADE_ASSERT(features() >= ConverterFeature::ConvertData, "ShaderTools::AbstractConverter::convertFileToData(): feature not supported", {}); @@ -376,7 +376,7 @@ Containers::Array AbstractConverter::convertFileToData(const Stage stage, /* 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); + out = doConvertFileToData(stage, filename); /* Otherwise use the callback and pass the data through to convertDataToData(). Mark the file as ready to be closed once conversion @@ -392,7 +392,7 @@ Containers::Array AbstractConverter::convertFileToData(const Stage stage, 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); + out = convertDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::convertFileToData():", stage, filename); } CORRADE_ASSERT(!out.deleter(), @@ -400,20 +400,20 @@ Containers::Array AbstractConverter::convertFileToData(const Stage stage, return out; } -Containers::Array AbstractConverter::doConvertFileToData(const Stage stage, const Containers::StringView from) { +Containers::Array AbstractConverter::doConvertFileToData(const Stage stage, const Containers::StringView filename) { /* 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); + return convertDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::convertFileToData():", stage, filename); /* Otherwise open the file directly */ } else { - if(!Utility::Directory::exists(from)) { - Error() << "ShaderTools::AbstractConverter::convertFileToData(): cannot open file" << from; + if(!Utility::Directory::exists(filename)) { + Error() << "ShaderTools::AbstractConverter::convertFileToData(): cannot open file" << filename; return {}; } - return doConvertDataToData(stage, Utility::Directory::read(from)); + return doConvertDataToData(stage, Utility::Directory::read(filename)); } } @@ -440,7 +440,7 @@ Containers::Array AbstractConverter::doLinkDataToData(Containers::ArrayVie CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented", {}); } -bool AbstractConverter::linkDataToFile(const Containers::ArrayView>> data, const Containers::StringView to) { +bool AbstractConverter::linkDataToFile(const Containers::ArrayView>> data, const Containers::StringView filename) { CORRADE_ASSERT(features() >= ConverterFeature::LinkData, "ShaderTools::AbstractConverter::linkDataToFile(): feature not supported", {}); CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly), @@ -454,45 +454,45 @@ bool AbstractConverter::linkDataToFile(const Containers::ArrayView out = doLinkDataToData(Containers::arrayCast>>(data)); if(!out) return false; - if(!Utility::Directory::write(to, out)) { - Error{} << "ShaderTools::AbstractConverter::linkDataToFile(): cannot write to file" << to; + if(!Utility::Directory::write(filename, out)) { + Error{} << "ShaderTools::AbstractConverter::linkDataToFile(): cannot write to file" << filename; return false; } return true; } -bool AbstractConverter::linkDataToFile(const std::initializer_list>> data, const Containers::StringView to) { - return linkDataToFile(Containers::arrayView(data), to); +bool AbstractConverter::linkDataToFile(const std::initializer_list>> data, const Containers::StringView filename) { + return linkDataToFile(Containers::arrayView(data), filename); } -Containers::Array AbstractConverter::linkDataToDataUsingInputFileCallbacks(const char* const prefix, const Containers::ArrayView> from) { - Containers::Array>> data{Containers::NoInit, from.size()}; +Containers::Array AbstractConverter::linkDataToDataUsingInputFileCallbacks(const char* const prefix, const Containers::ArrayView> filenames) { + Containers::Array>> data{Containers::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 != from.size(); ++i) { - const Containers::Optional> contents = _inputFileCallback(from[i].second, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData); + for(i = 0; i != filenames.size(); ++i) { + const Containers::Optional> contents = _inputFileCallback(filenames[i].second, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData); if(!contents) break; - data[i].first = from[i].first; + data[i].first = filenames[i].first; data[i].second = *contents; } /* If all input files loaded successfully, process */ Containers::Array out; - if(i == from.size()) out = doLinkDataToData(data); + if(i == filenames.size()) out = doLinkDataToData(data); /* Close again all input files that loaded successfully */ for(std::size_t ii = 0; ii != i; ++ii) - _inputFileCallback(from[ii].second, InputFileCallbackPolicy::Close, _inputFileCallbackUserData); + _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 != from.size()) { - Error{} << prefix << "cannot open file" << from[i].second; + if(i != filenames.size()) { + Error{} << prefix << "cannot open file" << filenames[i].second; return {}; } @@ -591,12 +591,12 @@ bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView AbstractConverter::linkFilesToData(const Containers::ArrayView> from) { +Containers::Array AbstractConverter::linkFilesToData(const Containers::ArrayView> filenames) { CORRADE_ASSERT(features() >= ConverterFeature::LinkData, "ShaderTools::AbstractConverter::linkFilesToData(): feature not supported", {}); CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly), "ShaderTools::AbstractConverter::linkFilesToData(): PreprocessOnly is not allowed in combination with linking", {}); - CORRADE_ASSERT(!from.empty(), + CORRADE_ASSERT(!filenames.empty(), "ShaderTools::AbstractConverter::linkFilesToData(): no files passed", {}); Containers::Array out; @@ -604,7 +604,7 @@ Containers::Array AbstractConverter::linkFilesToData(const Containers::Arr /* If input file callbacks are not set or the converter supports handling them directly, call into the implementation */ if(!_inputFileCallback || (doFeatures() & ConverterFeature::InputFileCallback)) { - out = doLinkFilesToData(from); + out = doLinkFilesToData(filenames); /* Otherwise use the callback and pass the data through to convertDataToData(). Mark the file as ready to be closed once conversion @@ -620,7 +620,7 @@ Containers::Array AbstractConverter::linkFilesToData(const Containers::Arr actual file loading to the default implementation (callback used in the base doLinkFilesToData() implementation, because this branch is never taken in that case) */ - out = linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToData():", from); + out = linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToData():", filenames); } CORRADE_ASSERT(!out.deleter(), @@ -628,32 +628,32 @@ Containers::Array AbstractConverter::linkFilesToData(const Containers::Arr return out; } -Containers::Array AbstractConverter::linkFilesToData(const std::initializer_list> from) { - return linkFilesToData(Containers::arrayView(from)); +Containers::Array AbstractConverter::linkFilesToData(const std::initializer_list> filenames) { + return linkFilesToData(Containers::arrayView(filenames)); } -Containers::Array AbstractConverter::doLinkFilesToData(const Containers::ArrayView> from) { +Containers::Array AbstractConverter::doLinkFilesToData(const Containers::ArrayView> filenames) { /* If callbacks are set, use them. This is the same implementation as in linkFilesToFile(), see the comment there for details. */ if(_inputFileCallback) { - return linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToData():", from); + return linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToData():", filenames); /* Otherwise open the files directly */ } else { - Containers::Array> fileData{from.size()}; - for(std::size_t i = 0; i != from.size(); ++i) { - if(!Utility::Directory::exists(from[i].second)) { - Error() << "ShaderTools::AbstractConverter::linkFilesToData(): cannot open file" << from[i].second; + Containers::Array> fileData{filenames.size()}; + for(std::size_t i = 0; i != filenames.size(); ++i) { + if(!Utility::Directory::exists(filenames[i].second)) { + Error() << "ShaderTools::AbstractConverter::linkFilesToData(): cannot open file" << filenames[i].second; return {}; } - fileData[i] = Utility::Directory::read(from[i].second); + fileData[i] = Utility::Directory::read(filenames[i].second); } /** @todo merge the allocations once we have an ArrayTuple */ - Containers::Array>> data{Containers::NoInit, from.size()}; - for(std::size_t i = 0; i != from.size(); ++i) { - data[i].first = from[i].first; + Containers::Array>> data{Containers::NoInit, filenames.size()}; + for(std::size_t i = 0; i != filenames.size(); ++i) { + data[i].first = filenames[i].first; data[i].second = fileData[i]; } diff --git a/src/Magnum/ShaderTools/AbstractConverter.h b/src/Magnum/ShaderTools/AbstractConverter.h index 61ff94112..ab3cc965c 100644 --- a/src/Magnum/ShaderTools/AbstractConverter.h +++ b/src/Magnum/ShaderTools/AbstractConverter.h @@ -765,7 +765,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac * @see @ref features(), @ref convertDataToData(), * @ref convertFileToData(), @ref convertFileToFile() */ - bool convertDataToFile(Stage stage, Containers::ArrayView data, Containers::StringView to); + bool convertDataToFile(Stage stage, Containers::ArrayView data, Containers::StringView filename); /** * @brief Convert shader file to a file @@ -792,7 +792,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac * @see @ref features(), @ref convertFileToFile(), * @ref convertDataToFile(), @ref convertDataToData() */ - Containers::Array convertFileToData(Stage stage, const Containers::StringView from); + Containers::Array convertFileToData(Stage stage, Containers::StringView filename); /** * @brief Link shader data together to a data @@ -820,10 +820,10 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac * @see @ref features(), @ref linkFilesToFile(), * @ref linkFilesToData(), @ref linkDataToData() */ - bool linkDataToFile(Containers::ArrayView>> data, Containers::StringView to); + bool linkDataToFile(Containers::ArrayView>> data, Containers::StringView filename); /** @overload */ - bool linkDataToFile(std::initializer_list>> data, Containers::StringView to); + bool linkDataToFile(std::initializer_list>> data, Containers::StringView filename); /** * @brief Link shader files together to a file @@ -856,10 +856,10 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac * @see @ref features(), @ref linkFilesToFile(), @ref linkDataToFile(), * @ref linkDataToData() */ - Containers::Array linkFilesToData(Containers::ArrayView> from); + Containers::Array linkFilesToData(Containers::ArrayView> filenames); /** @overload */ - Containers::Array linkFilesToData(std::initializer_list> from); + Containers::Array linkFilesToData(std::initializer_list> filenames); protected: /** @@ -911,7 +911,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::Array doConvertFileToData(Stage stage, Containers::StringView from); + virtual Containers::Array doConvertFileToData(Stage stage, Containers::StringView filename); /** * @brief Implementation for @ref linkFilesToFile() @@ -945,7 +945,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::Array doLinkFilesToData(Containers::ArrayView> from); + virtual Containers::Array doLinkFilesToData(Containers::ArrayView> filenames); private: /** @@ -1056,7 +1056,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac /* Used by convertFileToFile(), doConvertFileToFile(), convertFileToData() and doConvertFileToData() */ - MAGNUM_SHADERTOOLS_LOCAL Containers::Array convertDataToDataUsingInputFileCallbacks(const char* prefix, const Stage stage, Containers::StringView from); + MAGNUM_SHADERTOOLS_LOCAL Containers::Array convertDataToDataUsingInputFileCallbacks(const char* prefix, const Stage stage, Containers::StringView filename); /** * @brief Implementation for @ref convertDataToData() @@ -1070,7 +1070,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac /* Used by linkFilesToFile(), doLinkFilesToFile(), linkFilesToData() and doLinkFilesToData() */ - MAGNUM_SHADERTOOLS_LOCAL Containers::Array linkDataToDataUsingInputFileCallbacks(const char* prefix, Containers::ArrayView> from); + MAGNUM_SHADERTOOLS_LOCAL Containers::Array linkDataToDataUsingInputFileCallbacks(const char* prefix, Containers::ArrayView> filenames); /** * @brief Implementation for @ref linkDataToData() diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp index ca7788d6e..26e98ac27 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp @@ -361,13 +361,13 @@ bool AnyConverter::doConvertFileToFile(const Stage stage, const Containers::Stri return converter->convertFileToFile(stage, from, to); } -Containers::Array AnyConverter::doConvertFileToData(const Stage stage, const Containers::StringView from) { +Containers::Array AnyConverter::doConvertFileToData(const Stage stage, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); /* Prefer the explicitly set input format. If not set, fall back to detecting based on input and output extension. */ const Containers::StringView formatFrom = stringForFormat( - _state->inputFormat != Format::Unspecified ? _state->inputFormat : formatForExtension("ShaderTools::AnyConverter::convertFileToData():", from) + _state->inputFormat != Format::Unspecified ? _state->inputFormat : formatForExtension("ShaderTools::AnyConverter::convertFileToData():", filename) ); if(formatFrom.isEmpty()) return {}; if(_state->outputFormat == Format::Unspecified) { @@ -439,7 +439,7 @@ Containers::Array AnyConverter::doConvertFileToData(const Stage stage, con /* Try to convert the file (error output should be printed by the plugin itself) */ - return converter->convertFileToData(stage, from); + return converter->convertFileToData(stage, filename); } Containers::Array AnyConverter::doConvertDataToData(const Stage stage, const Containers::ArrayView from) { diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h index 859f20445..f1529dd53 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h @@ -144,7 +144,7 @@ class MAGNUM_ANYSHADERCONVERTER_EXPORT AnyConverter: public AbstractConverter { MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair doValidateFile(Stage stage, Containers::StringView filename) override; MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair doValidateData(Stage stage, Containers::ArrayView data) override; MAGNUM_ANYSHADERCONVERTER_LOCAL bool doConvertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to) override; - MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Array doConvertFileToData(Magnum::ShaderTools::Stage stage, Containers::StringView from) override; + MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Array doConvertFileToData(Magnum::ShaderTools::Stage stage, Containers::StringView filename) override; MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Array doConvertDataToData(Magnum::ShaderTools::Stage stage, Containers::ArrayView data) override; struct State; From 3184b92a4afe789f74fdcdc51bd1d2bf734b4b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 12:11:43 +0200 Subject: [PATCH 120/161] ShaderTools: a bit more consts. --- src/Magnum/ShaderTools/AbstractConverter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Magnum/ShaderTools/AbstractConverter.cpp b/src/Magnum/ShaderTools/AbstractConverter.cpp index 98c35db2a..dc9bb8f20 100644 --- a/src/Magnum/ShaderTools/AbstractConverter.cpp +++ b/src/Magnum/ShaderTools/AbstractConverter.cpp @@ -275,7 +275,7 @@ bool AbstractConverter::convertDataToFile(const Stage stage, const Containers::A /** @todo this needs expansion once output callbacks are supported as well */ /* Cast to a non-void type for more convenience */ - Containers::Array out = doConvertDataToData(stage, Containers::arrayCast(data)); + const Containers::Array out = doConvertDataToData(stage, Containers::arrayCast(data)); if(!out) return false; if(!Utility::Directory::write(filename, out)) { @@ -322,7 +322,7 @@ bool AbstractConverter::convertFileToFile(const Stage stage, const Containers::S 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 out = convertDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::convertFileToFile():", stage, from); + const Containers::Array out = convertDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::convertFileToFile():", stage, from); if(!out) return false; if(!Utility::Directory::write(to, out)) { @@ -451,7 +451,7 @@ bool AbstractConverter::linkDataToFile(const Containers::ArrayView out = doLinkDataToData(Containers::arrayCast>>(data)); + const Containers::Array out = doLinkDataToData(Containers::arrayCast>>(data)); if(!out) return false; if(!Utility::Directory::write(filename, out)) { @@ -530,7 +530,7 @@ bool AbstractConverter::linkFilesToFile(const Containers::ArrayView out = linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToFile():", from); + const Containers::Array out = linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToFile():", from); if(!out) return false; if(!Utility::Directory::write(to, out)) { From 823762657171456307cd68ad5b368558af49831a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 12:12:50 +0200 Subject: [PATCH 121/161] ShaderTools: update a TODO. --- src/Magnum/ShaderTools/AbstractConverter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Magnum/ShaderTools/AbstractConverter.cpp b/src/Magnum/ShaderTools/AbstractConverter.cpp index dc9bb8f20..d5558259c 100644 --- a/src/Magnum/ShaderTools/AbstractConverter.cpp +++ b/src/Magnum/ShaderTools/AbstractConverter.cpp @@ -571,7 +571,8 @@ bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView>> data{Containers::NoInit, from.size()}; for(std::size_t i = 0; i != from.size(); ++i) { data[i].first = from[i].first; From 06e039dbe7fd4c2e95960b97b2001822c79d54b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 13:41:44 +0200 Subject: [PATCH 122/161] Trade: reverse AbstractSceneConverter::convertToFile() argument order. It should be input first, output second, like with all other APIs. I remember I was trying something else here, but that didn't really make sense in the end. Also took that opportunity to get rid of one std::string. The original signature is a deprecated alias to the new one and will be removed in a future release. --- doc/changelog.dox | 4 ++++ src/Magnum/MeshTools/sceneconverter.cpp | 2 +- src/Magnum/Trade/AbstractSceneConverter.cpp | 16 +++++++++---- src/Magnum/Trade/AbstractSceneConverter.h | 23 ++++++++++++++----- .../Trade/Test/AbstractSceneConverterTest.cpp | 16 +++++++------ .../AnySceneConverter/AnySceneConverter.cpp | 8 ++++--- .../AnySceneConverter/AnySceneConverter.h | 2 +- .../Test/AnySceneConverterTest.cpp | 5 ++-- 8 files changed, 52 insertions(+), 24 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index ba9d293a0..93ee9a8e8 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -477,6 +477,10 @@ See also: @ref MAGNUM_BUILD_DEPRECATED is enabled, the returned type acts as a @ref Corrade::Containers::Optional but has (deprecated) implicit conversion to a @ref Corrade::Containers::Pointer to avoid breaking user code. +- The signature of @ref Trade::AbstractSceneConverter::convertToFile() was + changed to have input first and output second, for consistency with other + interfaces, together with a switch to @ref Containers::StringView. The + original signature is marked as deprecated. - @cpp Vk::hasVkFormat(Magnum::VertexFormat) @ce, @cpp Vk::hasVkFormat(Magnum::PixelFormat) @ce, @cpp Vk::hasVkFormat(Magnum::CompressedPixelFormat) @ce, diff --git a/src/Magnum/MeshTools/sceneconverter.cpp b/src/Magnum/MeshTools/sceneconverter.cpp index 0bdbc45cb..770f943fc 100644 --- a/src/Magnum/MeshTools/sceneconverter.cpp +++ b/src/Magnum/MeshTools/sceneconverter.cpp @@ -778,7 +778,7 @@ used.)") Debug{} << "Saving output with" << converterName << Debug::nospace << "..."; Duration d{conversionTime}; - if(!converter->convertToFile(args.value("output"), *mesh)) { + if(!converter->convertToFile(*mesh, args.value("output"))) { Error{} << "Cannot save file" << args.value("output"); return 5; } diff --git a/src/Magnum/Trade/AbstractSceneConverter.cpp b/src/Magnum/Trade/AbstractSceneConverter.cpp index 7807c8d0a..7af8a68cf 100644 --- a/src/Magnum/Trade/AbstractSceneConverter.cpp +++ b/src/Magnum/Trade/AbstractSceneConverter.cpp @@ -28,6 +28,8 @@ #include #include #include +#include /* Needed for Directory */ +#include #include #include @@ -43,7 +45,7 @@ namespace Magnum { namespace Trade { std::string AbstractSceneConverter::pluginInterface() { return /* [interface] */ -"cz.mosra.magnum.Trade.AbstractSceneConverter/0.1" +"cz.mosra.magnum.Trade.AbstractSceneConverter/0.1.1" /* [interface] */ ; } @@ -139,14 +141,20 @@ Containers::Array AbstractSceneConverter::doConvertToData(const MeshData&) CORRADE_ASSERT_UNREACHABLE("Trade::AbstractSceneConverter::convertToData(): mesh conversion advertised but not implemented", {}); } -bool AbstractSceneConverter::convertToFile(const std::string& filename, const MeshData& mesh) { +bool AbstractSceneConverter::convertToFile(const MeshData& mesh, const Containers::StringView filename) { CORRADE_ASSERT(features() >= SceneConverterFeature::ConvertMeshToFile, "Trade::AbstractSceneConverter::convertToFile(): mesh conversion not supported", {}); - return doConvertToFile(filename, mesh); + return doConvertToFile(mesh, filename); } -bool AbstractSceneConverter::doConvertToFile(const std::string& filename, const MeshData& mesh) { +#ifdef MAGNUM_BUILD_DEPRECATED +bool AbstractSceneConverter::convertToFile(const std::string& filename, const MeshData& mesh) { + return convertToFile(mesh, filename); +} +#endif + +bool AbstractSceneConverter::doConvertToFile(const MeshData& mesh, const Containers::StringView filename) { CORRADE_ASSERT(features() >= SceneConverterFeature::ConvertMeshToData, "Trade::AbstractSceneConverter::convertToFile(): mesh conversion advertised but not implemented", false); const auto data = doConvertToData(mesh); diff --git a/src/Magnum/Trade/AbstractSceneConverter.h b/src/Magnum/Trade/AbstractSceneConverter.h index 9b2d7aae3..b5587f4af 100644 --- a/src/Magnum/Trade/AbstractSceneConverter.h +++ b/src/Magnum/Trade/AbstractSceneConverter.h @@ -59,7 +59,7 @@ enum class SceneConverterFeature: UnsignedByte { /** * Converting a mesh to a file with - * @ref AbstractSceneConverter::convertToFile(const std::string&, const MeshData&). + * @ref AbstractSceneConverter::convertToFile(const MeshData&, Containers::StringView). */ ConvertMeshToFile = 1 << 2, @@ -171,8 +171,9 @@ checked by the implementation: @ref SceneConverterFeature::ConvertMeshInPlace is supported. - The function @ref doConvertToData(const MeshData&) is called only if @ref SceneConverterFeature::ConvertMeshToData is supported. -- The function @ref doConvertToFile(const std::string&, const MeshData&) is - called only if @ref SceneConverterFeature::ConvertMeshToFile is supported. +- The function @ref doConvertToFile(const MeshData&, Containers::StringView) + is called only if @ref SceneConverterFeature::ConvertMeshToFile is + supported. @m_class{m-block m-warning} @@ -298,6 +299,7 @@ class MAGNUM_TRADE_EXPORT AbstractSceneConverter: public PluginManager::Abstract /** * @brief Convert a mesh to a file + * @m_since_latest * * Available only if @ref SceneConverterFeature::ConvertMeshToFile or * @ref SceneConverterFeature::ConvertMeshToData is supported. Returns @@ -305,7 +307,16 @@ class MAGNUM_TRADE_EXPORT AbstractSceneConverter: public PluginManager::Abstract * @cpp false @ce otherwise. * @see @ref features(), @ref convertToData() */ - bool convertToFile(const std::string& filename, const MeshData& mesh); + bool convertToFile(const MeshData& mesh, Containers::StringView filename); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief convertToFile(const MeshData&, Containers::StringView) + * @m_deprecated_since_latest Use @ref convertToFile(const MeshData&, Containers::StringView) + * instead. + */ + CORRADE_DEPRECATED("use convertToFile(const MeshData&, Containers::StringView) instead") bool convertToFile(const std::string& filename, const MeshData& mesh); + #endif private: /** @@ -340,13 +351,13 @@ class MAGNUM_TRADE_EXPORT AbstractSceneConverter: public PluginManager::Abstract virtual Containers::Array doConvertToData(const MeshData& mesh); /** - * @brief Implementation for @ref convertToFile(const std::string&, const MeshData&) + * @brief Implementation for @ref convertToFile(const MeshData&, Containers::StringView) * * If @ref SceneConverterFeature::ConvertMeshToData is supported, * default implementation calls @ref doConvertToData(const MeshData&) * and saves the result to given file. */ - virtual bool doConvertToFile(const std::string& filename, const MeshData& mesh); + virtual bool doConvertToFile(const MeshData& mesh, Containers::StringView filename); SceneConverterFlags _flags; }; diff --git a/src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp b/src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp index cbf1baecb..6aca0b7ba 100644 --- a/src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractSceneConverterTest.cpp @@ -24,6 +24,8 @@ */ #include +#include +#include #include #include #include @@ -192,7 +194,7 @@ void AbstractSceneConverterTest::thingNotSupported() { converter.convert(mesh); converter.convertInPlace(mesh); converter.convertToData(mesh); - converter.convertToFile(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "mesh.out"), mesh); + converter.convertToFile(mesh, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "mesh.out")); CORRADE_COMPARE(out.str(), "Trade::AbstractSceneConverter::convert(): mesh conversion not supported\n" "Trade::AbstractSceneConverter::convertInPlace(): mesh conversion not supported\n" @@ -440,7 +442,7 @@ void AbstractSceneConverterTest::convertMeshToFile() { struct: AbstractSceneConverter { SceneConverterFeatures doFeatures() const override { return SceneConverterFeature::ConvertMeshToFile; } - bool doConvertToFile(const std::string& filename, const MeshData& mesh) override { + bool doConvertToFile(const MeshData& mesh, Containers::StringView filename) override { return Utility::Directory::write(filename, Containers::arrayView( {char(mesh.vertexCount())})); } } converter; @@ -451,7 +453,7 @@ void AbstractSceneConverterTest::convertMeshToFile() { Utility::Directory::rm(filename); CORRADE_VERIFY(!Utility::Directory::exists(filename)); - CORRADE_VERIFY(converter.convertToFile(filename, MeshData{MeshPrimitive::Triangles, 0xef})); + CORRADE_VERIFY(converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0xef}, filename)); CORRADE_COMPARE_AS(filename, "\xef", TestSuite::Compare::FileToString); } @@ -472,7 +474,7 @@ void AbstractSceneConverterTest::convertMeshToFileThroughData() { CORRADE_VERIFY(!Utility::Directory::exists(filename)); /* doConvertToFile() should call doConvertToData() */ - CORRADE_VERIFY(converter.convertToFile(filename, MeshData{MeshPrimitive::Triangles, 0xef})); + CORRADE_VERIFY(converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0xef}, filename)); CORRADE_COMPARE_AS(filename, "\xef", TestSuite::Compare::FileToString); } @@ -496,7 +498,7 @@ void AbstractSceneConverterTest::convertMeshToFileThroughDataFailed() { should be printed (the base implementation assumes the plugin does it) */ std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter.convertToFile(filename, MeshData{MeshPrimitive::Triangles, 0xef})); + CORRADE_VERIFY(!converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0xef}, filename)); CORRADE_VERIFY(!Utility::Directory::exists(filename)); CORRADE_COMPARE(out.str(), ""); } @@ -512,7 +514,7 @@ void AbstractSceneConverterTest::convertMeshToFileThroughDataNotWritable() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter.convertToFile("/some/path/that/does/not/exist", MeshData{MeshPrimitive::Triangles, 0xef})); + CORRADE_VERIFY(!converter.convertToFile(MeshData{MeshPrimitive::Triangles, 0xef}, "/some/path/that/does/not/exist")); CORRADE_COMPARE(out.str(), "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" "Trade::AbstractSceneConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); @@ -529,7 +531,7 @@ void AbstractSceneConverterTest::convertMeshToFileNotImplemented() { std::ostringstream out; Error redirectError{&out}; - converter.convertToFile(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "mesh.out"), MeshData{MeshPrimitive::Triangles, 6}); + converter.convertToFile(MeshData{MeshPrimitive::Triangles, 6}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "mesh.out")); CORRADE_COMPARE(out.str(), "Trade::AbstractSceneConverter::convertToFile(): mesh conversion advertised but not implemented\n"); } diff --git a/src/MagnumPlugins/AnySceneConverter/AnySceneConverter.cpp b/src/MagnumPlugins/AnySceneConverter/AnySceneConverter.cpp index 2dd20c1d3..b6bd015f3 100644 --- a/src/MagnumPlugins/AnySceneConverter/AnySceneConverter.cpp +++ b/src/MagnumPlugins/AnySceneConverter/AnySceneConverter.cpp @@ -25,6 +25,8 @@ #include "AnySceneConverter.h" +#include +#include #include #include #include @@ -45,7 +47,7 @@ SceneConverterFeatures AnySceneConverter::doFeatures() const { return SceneConverterFeature::ConvertMeshToFile; } -bool AnySceneConverter::doConvertToFile(const std::string& filename, const MeshData& mesh) { +bool AnySceneConverter::doConvertToFile(const MeshData& mesh, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); /** @todo lowercase only the extension, once Directory::split() is done */ @@ -80,10 +82,10 @@ bool AnySceneConverter::doConvertToFile(const std::string& filename, const MeshD /* Try to convert the file (error output should be printed by the plugin itself) */ - return converter->convertToFile(filename, mesh); + return converter->convertToFile(mesh, filename); } }} CORRADE_PLUGIN_REGISTER(AnySceneConverter, Magnum::Trade::AnySceneConverter, - "cz.mosra.magnum.Trade.AbstractSceneConverter/0.1") + "cz.mosra.magnum.Trade.AbstractSceneConverter/0.1.1") diff --git a/src/MagnumPlugins/AnySceneConverter/AnySceneConverter.h b/src/MagnumPlugins/AnySceneConverter/AnySceneConverter.h index 0c613534d..4dce14d30 100644 --- a/src/MagnumPlugins/AnySceneConverter/AnySceneConverter.h +++ b/src/MagnumPlugins/AnySceneConverter/AnySceneConverter.h @@ -104,7 +104,7 @@ class MAGNUM_ANYSCENECONVERTER_EXPORT AnySceneConverter: public AbstractSceneCon private: MAGNUM_ANYSCENECONVERTER_LOCAL SceneConverterFeatures doFeatures() const override; - MAGNUM_ANYSCENECONVERTER_LOCAL bool doConvertToFile(const std::string& filename, const MeshData& mesh) override; + MAGNUM_ANYSCENECONVERTER_LOCAL bool doConvertToFile(const MeshData& mesh, Containers::StringView filename) override; }; }} diff --git a/src/MagnumPlugins/AnySceneConverter/Test/AnySceneConverterTest.cpp b/src/MagnumPlugins/AnySceneConverter/Test/AnySceneConverterTest.cpp index 8cc02c5d8..e545d5dbf 100644 --- a/src/MagnumPlugins/AnySceneConverter/Test/AnySceneConverterTest.cpp +++ b/src/MagnumPlugins/AnySceneConverter/Test/AnySceneConverterTest.cpp @@ -24,6 +24,7 @@ */ #include +#include #include #include #include @@ -92,7 +93,7 @@ void AnySceneConverterTest::detect() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->convertToFile(data.filename, MeshData{MeshPrimitive::Triangles, 0})); + CORRADE_VERIFY(!converter->convertToFile(MeshData{MeshPrimitive::Triangles, 0}, data.filename)); /* Can't use raw string literals in macros on GCC 4.8 */ #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT CORRADE_COMPARE(out.str(), Utility::formatString( @@ -108,7 +109,7 @@ void AnySceneConverterTest::unknown() { Error redirectError{&output}; Containers::Pointer converter = _manager.instantiate("AnySceneConverter"); - CORRADE_VERIFY(!converter->convertToFile("mesh.obj", MeshData{MeshPrimitive::Triangles, 0})); + CORRADE_VERIFY(!converter->convertToFile(MeshData{MeshPrimitive::Triangles, 0}, "mesh.obj")); CORRADE_COMPARE(output.str(), "Trade::AnySceneConverter::convertToFile(): cannot determine the format of mesh.obj\n"); } From c82094dcb1aade6fb6c87e557d2057be65e6a0f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 14:38:10 +0200 Subject: [PATCH 123/161] Trade: fix a bad doc copypaste. --- src/Magnum/Trade/AbstractImageConverter.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index 92f29855a..ddcf5127c 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -161,11 +161,11 @@ The instances returned from various functions *by design* have no dependency on the converter instance and neither on the dynamic plugin module. In other words, you don't need to keep the converter instance (or the plugin manager instance) around in order to have the `*Data` instances valid. Moreover, all -@ref Corrade::Containers::Array instances returned through @ref Image, -@ref CompressedImage, @ref MeshData, @ref MaterialData, @ref AnimationData and -others are only allowed to have default deleters --- this is to avoid potential -dangling function pointer calls when destructing such instances after the -plugin module has been unloaded. +returned @relativeref{Corrade,Containers::Array} instances and +@relativeref{Corrade,Containers::Array} instances returned through +@ref ImageData are only allowed to have default deleters --- this is to avoid +potential dangling function pointer calls when destructing such instances after +the plugin module has been unloaded. @section Trade-AbstractImageConverter-subclassing Subclassing From 0581e72fd6babe339f7f8c884228eb7e2661db92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 16:07:16 +0200 Subject: [PATCH 124/161] Trade: use the "new" less annoying APIs in a test. --- src/Magnum/Trade/Test/AbstractImageConverterTest.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp index d19264257..4378effe2 100644 --- a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp @@ -408,18 +408,17 @@ void AbstractImageConverterTest::exportCompressedToDataCustomDeleter() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToData(): implementation is not allowed to use a custom Array deleter\n"); } +/* Used by convertImageDataToData() and convertImageDataToFile() */ class ImageDataConverter: public Trade::AbstractImageConverter { private: ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData|ImageConverterFeature::ConvertCompressedData; } Containers::Array doExportToData(const ImageView2D&) override { - Containers::Array out{Containers::InPlaceInit, {'B'}}; - return out; + return Containers::array({'B'}); }; Containers::Array doExportToData(const CompressedImageView2D&) override { - Containers::Array out{Containers::InPlaceInit, {'C'}}; - return out; + return Containers::array({'C'}); }; }; @@ -430,13 +429,13 @@ void AbstractImageConverterTest::exportImageDataToData() { /* Should get "B" when converting uncompressed */ ImageData2D image{PixelFormat::RGBA8Unorm, {}, nullptr}; CORRADE_COMPARE_AS(converter.exportToData(image), - (Containers::Array{Containers::InPlaceInit, {'B'}}), + Containers::arrayView({'B'}), TestSuite::Compare::Container); } { /* Should get "C" when converting compressed */ ImageData2D image{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}; CORRADE_COMPARE_AS(converter.exportToData(image), - (Containers::Array{Containers::InPlaceInit, {'C'}}), + Containers::arrayView({'C'}), TestSuite::Compare::Container); } } From d4c5b3f5666e05f22ad33a987fbe8fa1cbef2a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 17:33:52 +0200 Subject: [PATCH 125/161] Trade: refresh the AbstractImageConverter API. First and foremost I need to expand the interface to support 3D image conversion. But the interface was not great to begin with, so this takes the opportunity of an API break and does several things: * The `export*()` names were rather strange and I don't even remember why I chose that name (maybe because at first I wanted to have an "exporter" API as a counterpart to importers?) * In addition, there was no way to convert a compressed image to a compressed image (or to an uncompressed image) and adding the two missing variants would be a lot of combinations. So instead the new convert() returns an ImageData, which can be both, and thus also allows the converters to produce compressed or uncompressed output based on some runtime setting, without having to implement two (four?) separate functions for that and requiring users to know beforehand what type of an image will be created. * The ImageConverterFeature enum was named in a really strange way as well, with ConvertCompressedImage meaning "convert to a compressed image" while "ConvertCompressedData" instead meant "convert a compressed image to a data". Utter chaos. It also all implied 2D and on the other hand had a redundant `Image` in the name, so I went and remade the whole thing. As mentioned above, two of the enums now mean the same thing, and are both replaced with Convert2D. * Finally, similarly as changes elsewhere, I took this opportunity to get rid of std::string in the convertToFile() APIs. --- doc/changelog.dox | 24 + doc/generated/colormaps.cpp | 3 +- doc/generated/easings.cpp | 1 + doc/generated/primitives.cpp | 17 +- doc/generated/shaders.cpp | 3 +- src/Magnum/DebugTools/CompareImage.cpp | 3 +- src/Magnum/DebugTools/Screenshot.cpp | 3 +- .../DebugTools/Test/ScreenshotGLTest.cpp | 2 +- src/Magnum/Image.h | 21 - .../TextureTools/distancefieldconverter.cpp | 2 +- src/Magnum/Trade/AbstractImageConverter.cpp | 194 +++++--- src/Magnum/Trade/AbstractImageConverter.h | 378 ++++++++++++---- src/Magnum/Trade/ImageData.h | 1 + .../Trade/Test/AbstractImageConverterTest.cpp | 428 ++++++++++-------- src/Magnum/Trade/imageconverter.cpp | 2 +- .../AnyImageConverter/AnyImageConverter.cpp | 20 +- .../AnyImageConverter/AnyImageConverter.h | 4 +- .../Test/AnyImageConverterTest.cpp | 19 +- .../MagnumFontConverter.cpp | 2 +- .../Test/TgaImageConverterTest.cpp | 12 +- .../TgaImageConverter/TgaImageConverter.cpp | 12 +- .../TgaImageConverter/TgaImageConverter.h | 2 +- 22 files changed, 728 insertions(+), 425 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 93ee9a8e8..a797692ca 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -477,6 +477,30 @@ See also: @ref MAGNUM_BUILD_DEPRECATED is enabled, the returned type acts as a @ref Corrade::Containers::Optional but has (deprecated) implicit conversion to a @ref Corrade::Containers::Pointer to avoid breaking user code. +- @cpp Trade::ImageConverterFeature::ConvertImage @ce and + @cpp Trade::ImageConverterFeature::ConvertCompressedImage @ce; + @cpp Trade::AbstractImageConverter::exportToImage() @ce and + @cpp Trade::AbstractImageConverter::exportToCompressedImage() @ce are + deprecated in favor of an unifying + @ref Trade::ImageConverterFeature::Convert2D and a corresponding + @ref Trade::AbstractImageConverter::convert() that returns an + @ref Trade::ImageData2D and thus can handle both cases and follows a naming + scheme used elsewhere +- @cpp Trade::ImageConverterFeature::ConvertFile @ce, + @cpp Trade::ImageConverterFeature::ConvertCompressedFile @ce, + @cpp Trade::ImageConverterFeature::ConvertData @ce and + @cpp Trade::ImageConverterFeature::ConvertCompressedData @ce are deprecated + in favor of @ref Trade::ImageConverterFeature::Convert2DToFile, + @ref Trade::ImageConverterFeature::ConvertCompressed2DToFile, + @ref Trade::ImageConverterFeature::Convert2DToData and + @ref Trade::ImageConverterFeature::ConvertCompressed2DToData that more + clearly imply what's converted to what and make room for 3D image + conversion as well +- @cpp Trade::AbstractImageConverter::exportToData() @ce and + @cpp Trade::AbstractImageConverter::exportToFile() @ce are deprecated in + favor of @ref Trade::AbstractImageConverter::convertToData() and + @ref Trade::AbstractImageConverter::convertToFile() that follow a naming + scheme used elsewhere - The signature of @ref Trade::AbstractSceneConverter::convertToFile() was changed to have input first and output second, for consistency with other interfaces, together with a switch to @ref Containers::StringView. The diff --git a/doc/generated/colormaps.cpp b/doc/generated/colormaps.cpp index 8047a3a4d..c811e620a 100644 --- a/doc/generated/colormaps.cpp +++ b/doc/generated/colormaps.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include "Magnum/PixelFormat.h" @@ -62,7 +63,7 @@ int main() { {std::size_t(OutputSize.y()), std::size_t(OutputSize.x())}}; Utility::copy(src, dst); - if(!converter->exportToFile(ImageView2D{PixelFormat::RGB8Unorm, OutputSize, data}, image.second)) + if(!converter->convertToFile(ImageView2D{PixelFormat::RGB8Unorm, OutputSize, data}, image.second)) return 2; } } diff --git a/doc/generated/easings.cpp b/doc/generated/easings.cpp index 85b471c34..6e925cb6d 100644 --- a/doc/generated/easings.cpp +++ b/doc/generated/easings.cpp @@ -40,6 +40,7 @@ attribute to the element if you'd ever need that. */ +#include #include #include #include diff --git a/doc/generated/primitives.cpp b/doc/generated/primitives.cpp index 1a3bd00e1..ab42a42de 100644 --- a/doc/generated/primitives.cpp +++ b/doc/generated/primitives.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -198,7 +199,7 @@ int PrimitiveVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename)); } } @@ -217,7 +218,7 @@ int PrimitiveVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename)); } } @@ -242,7 +243,7 @@ int PrimitiveVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename)); } } @@ -273,7 +274,7 @@ int PrimitiveVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename)); } } @@ -304,7 +305,7 @@ int PrimitiveVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename)); } } @@ -348,7 +349,7 @@ int PrimitiveVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename)); } } @@ -371,7 +372,7 @@ int PrimitiveVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename)); } } @@ -394,7 +395,7 @@ int PrimitiveVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "primitives-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "primitives-" + filename)); } } diff --git a/doc/generated/shaders.cpp b/doc/generated/shaders.cpp index 35042926c..09dd64280 100644 --- a/doc/generated/shaders.cpp +++ b/doc/generated/shaders.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -145,7 +146,7 @@ int ShaderVisualizer::exec() { GL::AbstractFramebuffer::blit(multisampleFramebuffer, framebuffer, framebuffer.viewport(), GL::FramebufferBlit::Color); Image2D result = framebuffer.read(framebuffer.viewport(), {PixelFormat::RGBA8Unorm}); - converter->exportToFile(result, Utility::Directory::join("../", "shaders-" + filename)); + converter->convertToFile(result, Utility::Directory::join("../", "shaders-" + filename)); } _importer.reset(); diff --git a/src/Magnum/DebugTools/CompareImage.cpp b/src/Magnum/DebugTools/CompareImage.cpp index 73a37e779..2b9f4db6d 100644 --- a/src/Magnum/DebugTools/CompareImage.cpp +++ b/src/Magnum/DebugTools/CompareImage.cpp @@ -29,6 +29,7 @@ #include #include #include +#include /* for Directory */ #include #include #include @@ -734,7 +735,7 @@ void ImageComparatorBase::saveDiagnostic(TestSuite::ComparisonStatusFlags, Utili we're in the middle of a fail anyway (and everything will print messages to the output nevertheless). */ Containers::Pointer converter = _state->converterManager().loadAndInstantiate("AnyImageConverter"); - if(converter && converter->exportToFile(image, filename)) + if(converter && converter->convertToFile(image, filename)) out << "->" << filename; } diff --git a/src/Magnum/DebugTools/Screenshot.cpp b/src/Magnum/DebugTools/Screenshot.cpp index 1c5aac681..1619e27b2 100644 --- a/src/Magnum/DebugTools/Screenshot.cpp +++ b/src/Magnum/DebugTools/Screenshot.cpp @@ -26,6 +26,7 @@ #include "Screenshot.h" #include +#include #include #include @@ -78,7 +79,7 @@ bool screenshot(PluginManager::Manager& manager, return false; Image2D image = framebuffer.read(framebuffer.viewport(), {format}); - if(!converter->exportToFile(image, filename)) + if(!converter->convertToFile(image, filename)) return false; Debug{} << "DebugTools::screenshot(): saved a" << format << "image of size" << image.size() << "to" << filename; diff --git a/src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp b/src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp index 1a37d3afe..75b77d5cf 100644 --- a/src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp +++ b/src/Magnum/DebugTools/Test/ScreenshotGLTest.cpp @@ -311,7 +311,7 @@ void ScreenshotGLTest::saveFailed() { MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_VERIFY(!succeeded); - CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::exportToFile(): cannot determine the format of image.poo\n"); + CORRADE_COMPARE(out.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.poo\n"); } }}}} diff --git a/src/Magnum/Image.h b/src/Magnum/Image.h index 0b8d31fbc..ed0150d9a 100644 --- a/src/Magnum/Image.h +++ b/src/Magnum/Image.h @@ -47,11 +47,6 @@ template StridedA namespace Magnum { -#ifndef DOXYGEN_GENERATING_OUTPUT -/** @todo remove once AbstractImageConverter returns ImageData instead */ -namespace Trade { class AbstractImageConverter; } -#endif - /** @brief Image @@ -471,14 +466,6 @@ template class Image { Containers::Array release(); private: - #ifndef DOXYGEN_GENERATING_OUTPUT - /* For custom deleter checks. Not done in the constructors here because - the restriction is pointless when used outside of plugin - implementations. */ - /** @todo figure out a better way (return ImageData there instead?) */ - friend Trade::AbstractImageConverter; - #endif - PixelStorage _storage; PixelFormat _format; UnsignedInt _formatExtra; @@ -702,14 +689,6 @@ template class CompressedImage { Containers::Array release(); private: - #ifndef DOXYGEN_GENERATING_OUTPUT - /* For custom deleter checks. Not done in the constructors here because - the restriction is pointless when used outside of plugin - implementations. */ - /** @todo figure out a better way (return ImageData there instead?) */ - friend Trade::AbstractImageConverter; - #endif - /* To be made public once block size and block data size are stored together with the image */ explicit CompressedImage(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor& size, Containers::Array&& data) noexcept; diff --git a/src/Magnum/TextureTools/distancefieldconverter.cpp b/src/Magnum/TextureTools/distancefieldconverter.cpp index 087b93988..aa230cc30 100644 --- a/src/Magnum/TextureTools/distancefieldconverter.cpp +++ b/src/Magnum/TextureTools/distancefieldconverter.cpp @@ -215,7 +215,7 @@ int DistanceFieldConverter::exec() { /* Save image */ Image2D result{PixelFormat::R8Unorm}; output.image(0, result); - if(!converter->exportToFile(result, args.value("output"))) { + if(!converter->convertToFile(result, args.value("output"))) { Error() << "Cannot save file" << args.value("output"); return 5; } diff --git a/src/Magnum/Trade/AbstractImageConverter.cpp b/src/Magnum/Trade/AbstractImageConverter.cpp index 29db56c33..fc01a90b3 100644 --- a/src/Magnum/Trade/AbstractImageConverter.cpp +++ b/src/Magnum/Trade/AbstractImageConverter.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include /* for Directory */ #include #include #include @@ -45,7 +47,7 @@ namespace Magnum { namespace Trade { std::string AbstractImageConverter::pluginInterface() { return /* [interface] */ -"cz.mosra.magnum.Trade.AbstractImageConverter/0.2.1" +"cz.mosra.magnum.Trade.AbstractImageConverter/0.3" /* [interface] */ ; } @@ -93,109 +95,181 @@ void AbstractImageConverter::clearFlags(ImageConverterFlags flags) { setFlags(_flags & ~flags); } -Containers::Optional AbstractImageConverter::exportToImage(const ImageView2D& image) { - CORRADE_ASSERT(features() & ImageConverterFeature::ConvertImage, - "Trade::AbstractImageConverter::exportToImage(): feature not supported", {}); +Containers::Optional AbstractImageConverter::convert(const ImageView2D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert2D, + "Trade::AbstractImageConverter::convert(): 2D image conversion not supported", {}); - Containers::Optional out = doExportToImage(image); - CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::exportToImage(): implementation is not allowed to use a custom Array deleter", {}); + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); return out; } -Containers::Optional AbstractImageConverter::doExportToImage(const ImageView2D&) { - CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::exportToImage(): feature advertised but not implemented", {}); +Containers::Optional AbstractImageConverter::doConvert(const ImageView2D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): 2D image conversion advertised but not implemented", {}); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +Containers::Optional AbstractImageConverter::exportToImage(const ImageView2D& image) { + Containers::Optional out = convert(image); + if(!out) return {}; + if(out->isCompressed()) { + Error{} << "Trade::AbstractImageConverter::exportToImage(): implementation returned a compressed image"; + return {}; + } + + const PixelStorage storage = out->storage(); + const PixelFormat format = out->format(); + const UnsignedInt formatExtra = out->formatExtra(); + const UnsignedInt pixelSize = out->pixelSize(); + const Vector2i size = out->size(); + return Image2D{storage, format, formatExtra, pixelSize, size, out->release()}; } Containers::Optional AbstractImageConverter::exportToCompressedImage(const ImageView2D& image) { - CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedImage, - "Trade::AbstractImageConverter::exportToCompressedImage(): feature not supported", {}); + Containers::Optional out = convert(image); + if(!out) return {}; + if(!out->isCompressed()) { + Error{} << "Trade::AbstractImageConverter::exportToCompressedImage(): implementation returned an uncompressed image"; + return {}; + } + + const CompressedPixelStorage storage = out->compressedStorage(); + const CompressedPixelFormat format = out->compressedFormat(); + const Vector2i size = out->size(); + return CompressedImage2D{storage, format, size, out->release()}; +} +#endif - Containers::Optional out = doExportToCompressedImage(image); - CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::exportToCompressedImage(): implementation is not allowed to use a custom Array deleter", {}); +Containers::Optional AbstractImageConverter::convert(const CompressedImageView2D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2D, + "Trade::AbstractImageConverter::convert(): compressed 2D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); return out; } -Containers::Optional AbstractImageConverter::doExportToCompressedImage(const ImageView2D&) { - CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::exportToCompressedImage(): feature advertised but not implemented", {}); +Containers::Optional AbstractImageConverter::doConvert(const CompressedImageView2D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): compressed 2D image conversion advertised but not implemented", {}); } -Containers::Array AbstractImageConverter::exportToData(const ImageView2D& image) { - CORRADE_ASSERT(features() & ImageConverterFeature::ConvertData, - "Trade::AbstractImageConverter::exportToData(): feature not supported", nullptr); +Containers::Optional AbstractImageConverter::convert(const ImageData2D& image) { + return image.isCompressed() ? convert(CompressedImageView2D(image)) : convert(ImageView2D(image)); +} - Containers::Array out = doExportToData(image); - CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::exportToData(): implementation is not allowed to use a custom Array deleter", {}); +Containers::Array AbstractImageConverter::convertToData(const ImageView2D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert2DToData, + "Trade::AbstractImageConverter::convertToData(): 2D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); return out; } -Containers::Array AbstractImageConverter::doExportToData(const ImageView2D&) { - CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::exportToData(): feature advertised but not implemented", nullptr); +Containers::Array AbstractImageConverter::doConvertToData(const ImageView2D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): 2D image conversion advertised but not implemented", nullptr); } -Containers::Array AbstractImageConverter::exportToData(const CompressedImageView2D& image) { - CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedData, - "Trade::AbstractImageConverter::exportToData(): feature not supported", nullptr); +#ifdef MAGNUM_BUILD_DEPRECATED +Containers::Array AbstractImageConverter::exportToData(const ImageView2D& image) { + return convertToData(image); +} +#endif - Containers::Array out = doExportToData(image); - CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::exportToData(): implementation is not allowed to use a custom Array deleter", {}); +Containers::Array AbstractImageConverter::convertToData(const CompressedImageView2D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed2DToData, + "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); return out; } -Containers::Array AbstractImageConverter::doExportToData(const CompressedImageView2D&) { - CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::exportToData(): feature advertised but not implemented", nullptr); +Containers::Array AbstractImageConverter::doConvertToData(const CompressedImageView2D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion advertised but not implemented", nullptr); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +Containers::Array AbstractImageConverter::exportToData(const CompressedImageView2D& image) { + return convertToData(image); +} +#endif + +Containers::Array AbstractImageConverter::convertToData(const ImageData2D& image) { + return image.isCompressed() ? convertToData(CompressedImageView2D(image)) : convertToData(ImageView2D(image)); } +#ifdef MAGNUM_BUILD_DEPRECATED Containers::Array AbstractImageConverter::exportToData(const ImageData2D& image) { - return image.isCompressed() ? exportToData(CompressedImageView2D(image)) : exportToData(ImageView2D(image)); + return convertToData(image); } +#endif -bool AbstractImageConverter::exportToFile(const ImageView2D& image, const std::string& filename) { - CORRADE_ASSERT(features() & ImageConverterFeature::ConvertFile, - "Trade::AbstractImageConverter::exportToFile(): feature not supported", {}); +bool AbstractImageConverter::convertToFile(const ImageView2D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert2DToFile, + "Trade::AbstractImageConverter::convertToFile(): 2D image conversion not supported", {}); - return doExportToFile(image, filename); + return doConvertToFile(image, filename); } -bool AbstractImageConverter::doExportToFile(const ImageView2D& image, const std::string& filename) { - CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertData, "Trade::AbstractImageConverter::exportToFile(): feature advertised but not implemented", false); +bool AbstractImageConverter::doConvertToFile(const ImageView2D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert2DToData, "Trade::AbstractImageConverter::convertToFile(): 2D image conversion advertised but not implemented", false); - const auto data = doExportToData(image); + const auto data = doConvertToData(image); /* No deleter checks as it doesn't matter here */ if(!data) return false; if(!Utility::Directory::write(filename, data)) { - Error() << "Trade::AbstractImageConverter::exportToFile(): cannot write to file" << filename; + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; return false; } return true; } -bool AbstractImageConverter::exportToFile(const CompressedImageView2D& image, const std::string& filename) { - CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressedFile, - "Trade::AbstractImageConverter::exportToFile(): feature not supported", {}); +#ifdef MAGNUM_BUILD_DEPRECATED +bool AbstractImageConverter::exportToFile(const ImageView2D& image, const std::string& filename) { + return convertToFile(image, filename); +} +#endif + +bool AbstractImageConverter::convertToFile(const CompressedImageView2D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2DToFile, + "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported", {}); - return doExportToFile(image, filename); + return doConvertToFile(image, filename); } -bool AbstractImageConverter::doExportToFile(const CompressedImageView2D& image, const std::string& filename) { - CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressedData, "Trade::AbstractImageConverter::exportToFile(): feature advertised but not implemented", false); +bool AbstractImageConverter::doConvertToFile(const CompressedImageView2D& image, Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed2DToData, "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion advertised but not implemented", false); - const auto data = doExportToData(image); + const auto data = doConvertToData(image); /* No deleter checks as it doesn't matter here */ if(!data) return false; if(!Utility::Directory::write(filename, data)) { - Error() << "Trade::AbstractImageConverter::exportToFile(): cannot write to file" << filename; + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; return false; } return true; } +#ifdef MAGNUM_BUILD_DEPRECATED +bool AbstractImageConverter::exportToFile(const CompressedImageView2D& image, const std::string& filename) { + return convertToFile(image, filename); +} +#endif + +bool AbstractImageConverter::convertToFile(const ImageData2D& image, const Containers::StringView filename) { + return image.isCompressed() ? convertToFile(CompressedImageView2D(image), filename) : convertToFile(ImageView2D(image), filename); +} + +#ifdef MAGNUM_BUILD_DEPRECATED bool AbstractImageConverter::exportToFile(const ImageData2D& image, const std::string& filename) { - return image.isCompressed() ? exportToFile(CompressedImageView2D(image), filename) : exportToFile(ImageView2D(image), filename); + return convertToFile(image, filename); } +#endif Debug& operator<<(Debug& debug, const ImageConverterFeature value) { debug << "Trade::ImageConverterFeature" << Debug::nospace; @@ -203,28 +277,28 @@ Debug& operator<<(Debug& debug, const ImageConverterFeature value) { switch(value) { /* LCOV_EXCL_START */ #define _c(v) case ImageConverterFeature::v: return debug << "::" #v; - _c(ConvertImage) - _c(ConvertCompressedImage) - _c(ConvertFile) - _c(ConvertCompressedFile) - _c(ConvertData) - _c(ConvertCompressedData) + _c(Convert2D) + _c(ConvertCompressed2D) + _c(Convert2DToFile) + _c(ConvertCompressed2DToFile) + _c(Convert2DToData) + _c(ConvertCompressed2DToData) #undef _c /* LCOV_EXCL_STOP */ } - return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; + return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedInt(value)) << Debug::nospace << ")"; } Debug& operator<<(Debug& debug, const ImageConverterFeatures value) { return Containers::enumSetDebugOutput(debug, value, "Trade::ImageConverterFeatures{}", { - ImageConverterFeature::ConvertImage, - ImageConverterFeature::ConvertCompressedImage, - ImageConverterFeature::ConvertData, - ImageConverterFeature::ConvertCompressedData, - /* These are implied by Convert[Compressed]Data, so have to be last */ - ImageConverterFeature::ConvertFile, - ImageConverterFeature::ConvertCompressedFile}); + ImageConverterFeature::Convert2D, + ImageConverterFeature::ConvertCompressed2D, + ImageConverterFeature::Convert2DToData, + ImageConverterFeature::ConvertCompressed2DToData, + /* These are implied by Convert[Compressed]ToData, so have to be last */ + ImageConverterFeature::Convert2DToFile, + ImageConverterFeature::ConvertCompressed2DToFile}); } Debug& operator<<(Debug& debug, const ImageConverterFlag value) { diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index ddcf5127c..a8db45c57 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -43,44 +43,106 @@ namespace Magnum { namespace Trade { @see @ref ImageConverterFeatures, @ref AbstractImageConverter::features() */ -enum class ImageConverterFeature: UnsignedByte { +enum class ImageConverterFeature: UnsignedInt { /** - * Conversion to image with different format with - * @ref AbstractImageConverter::exportToImage() + * Convert a 2D image with + * @ref AbstractImageConverter::convert(const ImageView2D&) + * @m_since_latest */ - ConvertImage = 1 << 0, + Convert2D = 1 << 0, + #ifdef MAGNUM_BUILD_DEPRECATED /** - * Conversion to compressed image with - * @ref AbstractImageConverter::exportToCompressedImage() + * @copydoc ImageConverterFeature::Convert2D + * @m_deprecated_since_latest Use @ref ImageConverterFeature::Convert2D + * instead. */ - ConvertCompressedImage = 1 << 1, + ConvertImage CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2D instead") = Convert2D, /** - * Exporting to file with - * @ref AbstractImageConverter::exportToFile(const ImageView2D&, const std::string&) + * @copydoc ImageConverterFeature::Convert2D + * @m_deprecated_since_latest Use @ref ImageConverterFeature::Convert2D + * instead. Since @ref AbstractImageConverter::convert() is now + * capable of returning both uncompressed and compressed images, this + * feature is the same as @ref ImageConverterFeature::Convert2D, as + * opposed to @ref ImageConverterFeature::ConvertCompressed2D, which + * is about *input* images. */ - ConvertFile = 1 << 2, + ConvertCompressedImage CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2D instead") = Convert2D, + #endif /** - * Exporting to file with - * @ref AbstractImageConverter::exportToFile(const CompressedImageView2D&, const std::string&) + * Convert a compressed 2D image with + * @ref AbstractImageConverter::convert(const CompressedImageView2D&) + * @m_since_latest */ - ConvertCompressedFile = 1 << 3, + ConvertCompressed2D = 1 << 1, /** - * Exporting to raw data with - * @ref AbstractImageConverter::exportToData(const ImageView2D&). - * Implies @ref ImageConverterFeature::ConvertFile. + * Convert a 2D image to a file with + * @ref AbstractImageConverter::convertToFile(const ImageView2D&, Containers::StringView) + * @m_since_latest */ - ConvertData = ConvertFile|(1 << 4), + Convert2DToFile = 1 << 2, + #ifdef MAGNUM_BUILD_DEPRECATED /** - * Exporting compressed image to raw data with - * @ref AbstractImageConverter::exportToData(const CompressedImageView2D&). - * Implies @ref ImageConverterFeature::ConvertCompressedFile. + * @copydoc ImageConverterFeature::Convert2DToFile + * @m_deprecated_since_latest Use + * @ref ImageConverterFeature::Convert2DToFile instead. */ - ConvertCompressedData = ConvertCompressedFile|(1 << 4) + ConvertFile CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2DToFile instead") = Convert2DToFile, + #endif + + /** + * Convert a compressed 2D image to a file with + * @ref AbstractImageConverter::convertToFile(const CompressedImageView2D&, Containers::StringView) + * @m_since_latest + */ + ConvertCompressed2DToFile = 1 << 3, + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copydoc ImageConverterFeature::ConvertCompressed2DToFile + * @m_deprecated_since_latest Use + * @ref ImageConverterFeature::ConvertCompressed2DToFile instead. + */ + ConvertCompressedFile CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::ConvertCompressed2DToFile instead") = ConvertCompressed2DToFile, + #endif + + /** + * Convert a 2D image to raw data with + * @ref AbstractImageConverter::convertToData(const ImageView2D&). + * Implies @ref ImageConverterFeature::Convert2DToFile. + * @m_since_latest + */ + Convert2DToData = Convert2DToFile|(1 << 4), + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copydoc ImageConverterFeature::Convert2DToData + * @m_deprecated_since_latest Use + * @ref ImageConverterFeature::Convert2DToData instead. + */ + ConvertData CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2DToData instead") = Convert2DToData, + #endif + + /** + * Convert a compressed 2D image to raw data with + * @ref AbstractImageConverter::convertToData(const CompressedImageView2D&). + * Implies @ref ImageConverterFeature::ConvertCompressed2DToFile. + * @m_since_latest + */ + ConvertCompressed2DToData = ConvertCompressed2DToFile|(1 << 4), + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @copydoc ImageConverterFeature::ConvertCompressed2DToData + * @m_deprecated_since_latest Use + * @ref ImageConverterFeature::ConvertCompressed2DToData instead. + */ + ConvertCompressedData CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::ConvertCompressed2DToData instead") = ConvertCompressed2DToData, + #endif }; /** @@ -170,24 +232,24 @@ the plugin module has been unloaded. @section Trade-AbstractImageConverter-subclassing Subclassing The plugin needs to implement the @ref doFeatures() function and one or more of -@ref doExportToImage(), @ref doExportToCompressedImage(), @ref doExportToData() -or @ref doExportToFile() functions based on what features are supported. +@ref doConvert(), @ref doConvertToData() or @ref doConvertToFile() 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 doExportToImage() is called only if - @ref ImageConverterFeature::ConvertImage is supported. -- The function @ref doExportToCompressedImage() is called only if - @ref ImageConverterFeature::ConvertCompressedImage is supported. -- The function @ref doExportToData(const ImageView2D&) is called only if - @ref ImageConverterFeature::ConvertData is supported. -- The function @ref doExportToData(const CompressedImageView2D&) is called - only if @ref ImageConverterFeature::ConvertCompressedData is supported. -- The function @ref doExportToFile(const ImageView2D&, const std::string&) is - called only if @ref ImageConverterFeature::ConvertFile is supported. -- The function @ref doExportToFile(const CompressedImageView2D&, const std::string&) - is called only if @ref ImageConverterFeature::ConvertCompressedFile is +- The function @ref doConvert(const ImageView2D&) is called only if + @ref ImageConverterFeature::Convert2D is supported. +- The function @ref doConvert(const CompressedImageView2D&) is called only if + @ref ImageConverterFeature::ConvertCompressed2D is supported. +- The function @ref doConvertToData(const ImageView2D&) is called only if + @ref ImageConverterFeature::Convert2DToData is supported. +- The function @ref doConvertToData(const CompressedImageView2D&) is called + only if @ref ImageConverterFeature::ConvertCompressed2DToData is supported. +- The function @ref doConvertToFile(const ImageView2D&, Containers::StringView) + is called only if @ref ImageConverterFeature::Convert2DToFile is supported. +- The function @ref doConvertToFile(const CompressedImageView2D&, Containers::StringView) + is called only if @ref ImageConverterFeature::ConvertCompressed2DToFile is supported. @m_class{m-block m-warning} @@ -292,86 +354,194 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract void clearFlags(ImageConverterFlags flags); /** - * @brief Convert image to different format + * @brief Convert a 2D image + * @m_since_latest * - * Available only if @ref ImageConverterFeature::ConvertImage is + * Available only if @ref ImageConverterFeature::Convert2D is * supported. Returns converted image on success, - * @ref Containers::NullOpt otherwise. - * @see @ref features(), @ref exportToData(), @ref exportToFile() + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const CompressedImageView2D&), + * @ref convert(const ImageData2D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() */ - Containers::Optional exportToImage(const ImageView2D& image); + Containers::Optional convert(const ImageView2D& image); + #ifdef MAGNUM_BUILD_DEPRECATED /** - * @brief Convert image to compressed format + * @brief @copybrief convert(const ImageView2D&) + * @m_deprecated_since_latest Use @ref convert(const ImageView2D&) + * instead. + */ + CORRADE_DEPRECATED("use convert(const ImageView2D&) instead") Containers::Optional exportToImage(const ImageView2D& image); + + /** + * @brief Convert a 2D image to compressed format + * @m_deprecated_since_latest Use @ref convert(const ImageView2D&) + * instead. + */ + CORRADE_DEPRECATED("use convert(const ImageView2D&) instead") Containers::Optional exportToCompressedImage(const ImageView2D& image); + #endif + + /** + * @brief Convert a compressed 2D image + * @m_since_latest * - * Available only if @ref ImageConverterFeature::ConvertCompressedImage - * is supported. Returns converted image on success, - * @ref Containers::NullOpt otherwise. - * @see @ref features(), @ref exportToData(), @ref exportToFile() + * Available only if @ref ImageConverterFeature::ConvertCompressed2D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const ImageView2D&), + * @ref convert(const ImageData2D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() */ - Containers::Optional exportToCompressedImage(const ImageView2D& image); + Containers::Optional convert(const CompressedImageView2D& image); /** - * @brief Export image to raw data + * @brief Convert a 2D image data + * @m_since_latest * - * Available only if @ref ImageConverterFeature::ConvertData is - * supported. Returns data on success, zero-sized array otherwise. - * @see @ref features(), @ref exportToImage(), - * @ref exportToFile(const ImageView2D&, const std::string&) + * Based on whether the image is compressed or not, calls either + * @ref convert(const ImageView2D&) or + * @ref convert(const CompressedImageView2D&). See documentation of + * these two functions for details. + * @see @ref ImageData::isCompressed() */ - Containers::Array exportToData(const ImageView2D& image); + Containers::Optional convert(const ImageData2D& image); /** - * @brief Export compressed image to raw data + * @brief Convert a 2D image to a raw data + * @m_since_latest * - * Available only if @ref ImageConverterFeature::ConvertCompressedData - * is supported. Returns data on success, zero-sized array otherwise. - * @see @ref features(), @ref exportToCompressedImage(), - * @ref exportToFile(const CompressedImageView2D&, const std::string&) + * Available only if @ref ImageConverterFeature::Convert2DToData is + * supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const CompressedImageView2D&), + * @ref convertToData(const ImageData2D&), @ref convert(), + * @ref convertToFile() */ - Containers::Array exportToData(const CompressedImageView2D& image); + Containers::Array convertToData(const ImageView2D& image); + #ifdef MAGNUM_BUILD_DEPRECATED /** - * @brief Export image to raw data + * @brief @copybrief convertToData(const ImageView2D&) + * @m_deprecated_since_latest Use @ref convertToData(const ImageView2D&) + * instead. + */ + CORRADE_DEPRECATED("use convertToData(const ImageView2D&) instead") Containers::Array exportToData(const ImageView2D& image); + #endif + + /** + * @brief Convert a compressed 2D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed2DToData + * is supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const ImageView2D&), + * @ref convertToData(const ImageData2D&), @ref convert(), + * @ref convertToFile() + */ + Containers::Array convertToData(const CompressedImageView2D& image); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief convertToData(const CompressedImageView2D&) + * @m_deprecated_since_latest Use + * @ref convertToData(const CompressedImageView2D&) instead. + */ + CORRADE_DEPRECATED("use convertToData(const CompressedImageView2D&) instead") Containers::Array exportToData(const CompressedImageView2D& image); + #endif + + /** + * @brief Convert a 2D image data to a raw data + * @m_since_latest * * Based on whether the image is compressed or not, calls either - * @ref exportToData(const ImageView2D&) or - * @ref exportToData(const CompressedImageView2D&). See documentation - * of those two functions for details. + * @ref convertToData(const ImageView2D&) or + * @ref convertToData(const CompressedImageView2D&). See documentation + * of these two functions for details. + * @see @ref ImageData::isCompressed() */ - Containers::Array exportToData(const ImageData2D& image); + Containers::Array convertToData(const ImageData2D& image); + #ifdef MAGNUM_BUILD_DEPRECATED /** - * @brief Export image to file + * @brief @copybrief convertToData(const ImageData2D&) + * @m_deprecated_since_latest Use @ref convertToData(const ImageData2D&) + * instead. + */ + CORRADE_DEPRECATED("use convertToData(const ImageView2D&) instead") Containers::Array exportToData(const ImageData2D& image); + #endif + + /** + * @brief Convert a 2D image to a file + * @m_since_latest * - * Available only if @ref ImageConverterFeature::ConvertFile or - * @ref ImageConverterFeature::ConvertData is supported. Returns + * Available only if @ref ImageConverterFeature::Convert2DToFile or + * @ref ImageConverterFeature::Convert2DToData is supported. Returns * @cpp true @ce on success, @cpp false @ce otherwise. - * @see @ref features(), @ref exportToImage(), - * @ref exportToData(const ImageView2D&) + * @see @ref features(), @ref convertToFile(const CompressedImageView2D&, Containers::StringView), + * @ref convertToFile(const ImageData2D&, Containers::StringView), + * @ref convert(), @ref convertToData() */ - bool exportToFile(const ImageView2D& image, const std::string& filename); + bool convertToFile(const ImageView2D& image, Containers::StringView filename); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief convertToFile(const ImageView2D&, Containers::StringView) + * @m_deprecated_since_latest Use + * @ref convertToFile(const ImageView2D&, Containers::StringView) + * instead. + */ + CORRADE_DEPRECATED("use convertToFile(const ImageView2D&, Containers::StringView) instead") bool exportToFile(const ImageView2D& image, const std::string& filename); + #endif /** - * @brief Export compressed image to file + * @brief Convert a compressed 2D image to a file + * @m_since_latest * - * Available only if @ref ImageConverterFeature::ConvertCompressedFile - * or @ref ImageConverterFeature::ConvertCompressedData is supported. - * Returns @cpp true @ce on success, @cpp false @ce otherwise. - * @see @ref features(), @ref exportToCompressedImage(), - * @ref exportToData(const CompressedImageView2D&) + * Available only if @ref ImageConverterFeature::ConvertCompressed2DToFile + * or @ref ImageConverterFeature::ConvertCompressed2DToData is + * supported. Returns @cpp true @ce on success, @cpp false @ce + * otherwise. + * @see @ref features(), @ref convertToFile(const ImageView2D&, Containers::StringView), + * @ref convertToFile(const ImageData2D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const CompressedImageView2D& image, Containers::StringView filename); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief convertToFile(const CompressedImageView2D&, Containers::StringView) + * @m_deprecated_since_latest Use + * @ref convertToFile(const CompressedImageView2D&, Containers::StringView) + * instead. */ - bool exportToFile(const CompressedImageView2D& image, const std::string& filename); + CORRADE_DEPRECATED("use convertToFile(const CompressedImageView2D&, Containers::StringView) instead") bool exportToFile(const CompressedImageView2D& image, const std::string& filename); + #endif /** - * @brief Export image to file + * @brief Convert a 2D image data to a file + * @m_since_latest * * Based on whether the image is compressed or not, calls either - * @ref exportToFile(const ImageView2D&, const std::string&) or - * @ref exportToFile(const CompressedImageView2D&, const std::string&). - * See documentation of those two functions for details. + * @ref convertToFile(const ImageView2D&, Containers::StringView) or + * @ref convertToFile(const CompressedImageView2D&, Containers::StringView). + * See documentation of these two functions for details. + * @see @ref ImageData::isCompressed() */ - bool exportToFile(const ImageData2D& image, const std::string& filename); + bool convertToFile(const ImageData2D& image, Containers::StringView filename); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief convertToFile(const ImageData2D&, Containers::StringView) + * @m_deprecated_since_latest Use + * @ref convertToFile(const ImageData2D&, Containers::StringView) + * instead. + */ + CORRADE_DEPRECATED("use convertToFile(const ImageData2D&, Containers::StringView) instead") bool exportToFile(const ImageData2D& image, const std::string& filename); + #endif private: /** @brief Implementation for @ref features() */ @@ -392,35 +562,49 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ virtual void doSetFlags(ImageConverterFlags flags); - /** @brief Implementation for @ref exportToImage() */ - virtual Containers::Optional doExportToImage(const ImageView2D& image); + /** + * @brief Implementation for @ref convert(const ImageView2D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const ImageView2D& image); - /** @brief Implementation for @ref exportToCompressedImage() */ - virtual Containers::Optional doExportToCompressedImage(const ImageView2D& image); + /** + * @brief Implementation for @ref convert(const CompressedImageView2D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const CompressedImageView2D& image); - /** @brief Implementation for @ref exportToData(const ImageView2D&) */ - virtual Containers::Array doExportToData(const ImageView2D& image); + /** + * @brief Implementation for @ref convertToData(const ImageView2D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const ImageView2D& image); - /** @brief Implementation for @ref exportToData(const CompressedImageView2D&) */ - virtual Containers::Array doExportToData(const CompressedImageView2D& image); + /** + * @brief Implementation for @ref convertToData(const CompressedImageView2D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const CompressedImageView2D& image); /** - * @brief Implementation for @ref exportToFile(const ImageView2D&, const std::string&) + * @brief Implementation for @ref convertToFile(const ImageView2D&, Containers::StringView) + * @m_since_latest * - * If @ref ImageConverterFeature::ConvertData is supported, default - * implementation calls @ref doExportToData(const ImageView2D&) and + * If @ref ImageConverterFeature::Convert2DToData is supported, default + * implementation calls @ref doConvertToData(const ImageView2D&) and * saves the result to given file. */ - virtual bool doExportToFile(const ImageView2D& image, const std::string& filename); + virtual bool doConvertToFile(const ImageView2D& image, Containers::StringView filename); /** - * @brief Implementation for @ref exportToFile(const CompressedImageView2D&, const std::string&) + * @brief Implementation for @ref convertToFile(const CompressedImageView2D&, Containers::StringView) + * @m_since_latest * - * If @ref ImageConverterFeature::ConvertCompressedData is supported, - * default implementation calls @ref doExportToData(const CompressedImageView2D&) + * If @ref ImageConverterFeature::ConvertCompressed2DToData is + * supported, default implementation calls @ref doConvertToData(const CompressedImageView2D&) * and saves the result to given file. */ - virtual bool doExportToFile(const CompressedImageView2D& image, const std::string& filename); + virtual bool doConvertToFile(const CompressedImageView2D& image, Containers::StringView filename); ImageConverterFlags _flags; }; diff --git a/src/Magnum/Trade/ImageData.h b/src/Magnum/Trade/ImageData.h index 54e2b1245..0d8047712 100644 --- a/src/Magnum/Trade/ImageData.h +++ b/src/Magnum/Trade/ImageData.h @@ -675,6 +675,7 @@ template class ImageData { the restriction is pointless when used outside of plugin implementations. */ friend AbstractImporter; + friend AbstractImageConverter; explicit ImageData(CompressedPixelStorage storage, UnsignedInt format, const VectorTypeFor& size, Containers::Array&& data, const void* importerState = nullptr) noexcept; diff --git a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp index 4378effe2..bc1eb317e 100644 --- a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -53,37 +55,39 @@ struct AbstractImageConverterTest: TestSuite::Tester { void thingNotSupported(); - void exportToImage(); - void exportToImageNotImplemented(); - void exportToImageCustomDeleter(); + void convert2D(); + void convert2DNotImplemented(); + void convert2DCustomDeleter(); - void exportToCompressedImage(); - void exportToCompressedImageNotImplemented(); - void exportToCompressedImageCustomDeleter(); + void convertCompressed2D(); + void convertCompressed2DNotImplemented(); + void convertCompressed2DCustomDeleter(); - void exportToData(); - void exportToDataNotImplemented(); - void exportToDataCustomDeleter(); + void convertImageData2D(); - void exportCompressedToData(); - void exportCompressedToDataNotImplemented(); - void exportCompressedToDataCustomDeleter(); + void convert2DToData(); + void convert2DToDataNotImplemented(); + void convert2DToDataCustomDeleter(); - void exportImageDataToData(); + void convertCompressed2DToData(); + void convertCompressed2DToDataNotImplemented(); + void convertCompressed2DToDataCustomDeleter(); - void exportToFile(); - void exportToFileThroughData(); - void exportToFileThroughDataFailed(); - void exportToFileThroughDataNotWritable(); - void exportToFileNotImplemented(); + void convertImageData2DToData(); - void exportCompressedToFile(); - void exportCompressedToFileThroughData(); - void exportCompressedToFileThroughDataFailed(); - void exportCompressedToFileThroughDataNotWritable(); - void exportCompressedToFileNotImplemented(); + void convert2DToFile(); + void convert2DToFileThroughData(); + void convert2DToFileThroughDataFailed(); + void convert2DToFileThroughDataNotWritable(); + void convert2DToFileNotImplemented(); - void exportImageDataToFile(); + void convertCompressed2DToFile(); + void convertCompressed2DToFileThroughData(); + void convertCompressed2DToFileThroughDataFailed(); + void convertCompressed2DToFileThroughDataNotWritable(); + void convertCompressed2DToFileNotImplemented(); + + void convertImageData2DToFile(); void debugFeature(); void debugFeatures(); @@ -100,37 +104,39 @@ AbstractImageConverterTest::AbstractImageConverterTest() { &AbstractImageConverterTest::thingNotSupported, - &AbstractImageConverterTest::exportToImage, - &AbstractImageConverterTest::exportToImageNotImplemented, - &AbstractImageConverterTest::exportToImageCustomDeleter, + &AbstractImageConverterTest::convert2D, + &AbstractImageConverterTest::convert2DNotImplemented, + &AbstractImageConverterTest::convert2DCustomDeleter, + + &AbstractImageConverterTest::convertCompressed2D, + &AbstractImageConverterTest::convertCompressed2DNotImplemented, + &AbstractImageConverterTest::convertCompressed2DCustomDeleter, - &AbstractImageConverterTest::exportToCompressedImage, - &AbstractImageConverterTest::exportToCompressedImageNotImplemented, - &AbstractImageConverterTest::exportToCompressedImageCustomDeleter, + &AbstractImageConverterTest::convertImageData2D, - &AbstractImageConverterTest::exportToData, - &AbstractImageConverterTest::exportToDataNotImplemented, - &AbstractImageConverterTest::exportToDataCustomDeleter, + &AbstractImageConverterTest::convert2DToData, + &AbstractImageConverterTest::convert2DToDataNotImplemented, + &AbstractImageConverterTest::convert2DToDataCustomDeleter, - &AbstractImageConverterTest::exportCompressedToData, - &AbstractImageConverterTest::exportCompressedToDataNotImplemented, - &AbstractImageConverterTest::exportCompressedToDataCustomDeleter, + &AbstractImageConverterTest::convertCompressed2DToData, + &AbstractImageConverterTest::convertCompressed2DToDataNotImplemented, + &AbstractImageConverterTest::convertCompressed2DToDataCustomDeleter, - &AbstractImageConverterTest::exportImageDataToData, + &AbstractImageConverterTest::convertImageData2DToData, - &AbstractImageConverterTest::exportToFile, - &AbstractImageConverterTest::exportToFileThroughData, - &AbstractImageConverterTest::exportToFileThroughDataFailed, - &AbstractImageConverterTest::exportToFileThroughDataNotWritable, - &AbstractImageConverterTest::exportToFileNotImplemented, + &AbstractImageConverterTest::convert2DToFile, + &AbstractImageConverterTest::convert2DToFileThroughData, + &AbstractImageConverterTest::convert2DToFileThroughDataFailed, + &AbstractImageConverterTest::convert2DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convert2DToFileNotImplemented, - &AbstractImageConverterTest::exportCompressedToFile, - &AbstractImageConverterTest::exportCompressedToFileThroughData, - &AbstractImageConverterTest::exportCompressedToFileThroughDataFailed, - &AbstractImageConverterTest::exportCompressedToFileThroughDataNotWritable, - &AbstractImageConverterTest::exportCompressedToFileNotImplemented, + &AbstractImageConverterTest::convertCompressed2DToFile, + &AbstractImageConverterTest::convertCompressed2DToFileThroughData, + &AbstractImageConverterTest::convertCompressed2DToFileThroughDataFailed, + &AbstractImageConverterTest::convertCompressed2DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convertCompressed2DToFileNotImplemented, - &AbstractImageConverterTest::exportImageDataToFile, + &AbstractImageConverterTest::convertImageData2DToFile, &AbstractImageConverterTest::debugFeature, &AbstractImageConverterTest::debugFeatures, @@ -209,241 +215,271 @@ void AbstractImageConverterTest::thingNotSupported() { std::ostringstream out; Error redirectError{&out}; - converter.exportToImage(ImageView2D{PixelFormat::R8Unorm, {4, 6}, Containers::ArrayView{nullptr, 24}}); - converter.exportToCompressedImage(ImageView2D{PixelFormat::R8Unorm, {16, 8}, Containers::ArrayView{nullptr, 128}}); - converter.exportToData(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, Containers::ArrayView{nullptr, 96}}); - converter.exportToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); - converter.exportToFile(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); - converter.exportToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + converter.convert(ImageView2D{PixelFormat::R8Unorm, {4, 6}, Containers::ArrayView{nullptr, 24}}); + converter.convert(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}); + converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, Containers::ArrayView{nullptr, 96}}); + converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + converter.convertToFile(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + converter.convertToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); CORRADE_COMPARE(out.str(), - "Trade::AbstractImageConverter::exportToImage(): feature not supported\n" - "Trade::AbstractImageConverter::exportToCompressedImage(): feature not supported\n" - "Trade::AbstractImageConverter::exportToData(): feature not supported\n" - "Trade::AbstractImageConverter::exportToData(): feature not supported\n" - "Trade::AbstractImageConverter::exportToFile(): feature not supported\n" - "Trade::AbstractImageConverter::exportToFile(): feature not supported\n"); + "Trade::AbstractImageConverter::convert(): 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convert(): compressed 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported\n"); } -void AbstractImageConverterTest::exportToImage() { +void AbstractImageConverterTest::convert2D() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertImage; } - Containers::Optional doExportToImage(const ImageView2D& image) override { - return Image2D{PixelFormat::RGBA8Unorm, image.size(), Containers::Array{96}}; + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2D; } + Containers::Optional doConvert(const ImageView2D& image) override { + return ImageData2D{PixelFormat::RGBA8Unorm, image.size(), Containers::Array{96}}; } } converter; - Containers::Optional actual = converter.exportToImage(ImageView2D{PixelFormat::R8Unorm, {4, 6}, Containers::ArrayView{nullptr, 24}}); + Containers::Optional actual = converter.convert(ImageView2D{PixelFormat::R8Unorm, {4, 6}, Containers::ArrayView{nullptr, 24}}); CORRADE_VERIFY(actual); + CORRADE_VERIFY(!actual->isCompressed()); CORRADE_COMPARE(actual->data().size(), 96); CORRADE_COMPARE(actual->size(), (Vector2i{4, 6})); } -void AbstractImageConverterTest::exportToImageNotImplemented() { +void AbstractImageConverterTest::convert2DNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertImage; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2D; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToImage(ImageView2D{PixelFormat::R8Unorm, {4, 6}, Containers::ArrayView{nullptr, 128}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToImage(): feature advertised but not implemented\n"); + converter.convert(ImageView2D{PixelFormat::R8Unorm, {4, 6}, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): 2D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::exportToImageCustomDeleter() { +void AbstractImageConverterTest::convert2DCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertImage; } - Containers::Optional doExportToImage(const ImageView2D&) override { - return Image2D{PixelFormat::RGBA8Unorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2D; } + Containers::Optional doConvert(const ImageView2D&) override { + return ImageData2D{PixelFormat::RGBA8Unorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToImage(ImageView2D{PixelFormat::R8Unorm, {}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToImage(): implementation is not allowed to use a custom Array deleter\n"); + converter.convert(ImageView2D{PixelFormat::R8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); } -void AbstractImageConverterTest::exportToCompressedImage() { +void AbstractImageConverterTest::convertCompressed2D() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedImage; } - Containers::Optional doExportToCompressedImage(const ImageView2D& image) override { - return CompressedImage2D{CompressedPixelFormat::Bc1RGBAUnorm, image.size(), Containers::Array{64}}; + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2D; } + Containers::Optional doConvert(const CompressedImageView2D& image) override { + return ImageData2D{image.format(), image.size(), Containers::Array{64}}; } } converter; - Containers::Optional actual = converter.exportToCompressedImage(ImageView2D{PixelFormat::R8Unorm, {16, 8}, Containers::ArrayView{nullptr, 128}}); + Containers::Optional actual = converter.convert(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 128}}); CORRADE_VERIFY(actual); + CORRADE_VERIFY(actual->isCompressed()); CORRADE_COMPARE(actual->data().size(), 64); CORRADE_COMPARE(actual->size(), (Vector2i{16, 8})); } -void AbstractImageConverterTest::exportToCompressedImageNotImplemented() { +void AbstractImageConverterTest::convertCompressed2DNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedImage; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2D; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToCompressedImage(ImageView2D{PixelFormat::R8Unorm, {16, 8}, Containers::ArrayView{nullptr, 128}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToCompressedImage(): feature advertised but not implemented\n"); + converter.convert(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): compressed 2D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::exportToCompressedImageCustomDeleter() { +void AbstractImageConverterTest::convertCompressed2DCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedImage; } - Containers::Optional doExportToCompressedImage(const ImageView2D&) override { - return CompressedImage2D{CompressedPixelFormat::Bc1RGBAUnorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2D; } + Containers::Optional doConvert(const CompressedImageView2D&) override { + return ImageData2D{CompressedPixelFormat::Bc1RGBAUnorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToCompressedImage(ImageView2D{PixelFormat::R8Unorm, {}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToCompressedImage(): implementation is not allowed to use a custom Array deleter\n"); + converter.convert(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); } -void AbstractImageConverterTest::exportToData() { +void AbstractImageConverterTest::convertImageData2D() { + struct: Trade::AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2D|ImageConverterFeature::ConvertCompressed2D; } + + Containers::Optional doConvert(const ImageView2D&) override { + return ImageData2D{PixelFormat::R8Unorm, {}, Containers::array({'B'})}; + }; + + Containers::Optional doConvert(const CompressedImageView2D&) override { + return ImageData2D{PixelFormat::R8Unorm, {}, Containers::array({'C'})}; + }; + } converter; + + { + /* Should get "B" when converting uncompressed */ + ImageData2D image{PixelFormat::RGBA8Unorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + } { + /* Should get "C" when converting compressed */ + ImageData2D image{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); + } +} + +void AbstractImageConverterTest::convert2DToData() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData; } - Containers::Array doExportToData(const ImageView2D& image) override { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } + Containers::Array doConvertToData(const ImageView2D& image) override { return Containers::Array{nullptr, std::size_t(image.size().product())}; } } converter; - Containers::Array actual = converter.exportToData(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, Containers::ArrayView{nullptr, 96}}); + Containers::Array actual = converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, Containers::ArrayView{nullptr, 96}}); CORRADE_COMPARE(actual.size(), 24); } -void AbstractImageConverterTest::exportToDataNotImplemented() { +void AbstractImageConverterTest::convert2DToDataNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToData(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, Containers::ArrayView{nullptr, 96}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToData(): feature advertised but not implemented\n"); + converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): 2D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::exportToDataCustomDeleter() { +void AbstractImageConverterTest::convert2DToDataCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData; } - Containers::Array doExportToData(const ImageView2D&) override { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } + Containers::Array doConvertToData(const ImageView2D&) override { return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToData(ImageView2D{PixelFormat::RGBA8Unorm, {}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToData(): implementation is not allowed to use a custom Array deleter\n"); + converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); } -void AbstractImageConverterTest::exportCompressedToData() { +void AbstractImageConverterTest::convertCompressed2DToData() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedData; } - Containers::Array doExportToData(const CompressedImageView2D& image) override { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + Containers::Array doConvertToData(const CompressedImageView2D& image) override { return Containers::Array{nullptr, std::size_t(image.size().product())}; } } converter; - Containers::Array actual = converter.exportToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + Containers::Array actual = converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); CORRADE_COMPARE(actual.size(), 128); } -void AbstractImageConverterTest::exportCompressedToDataNotImplemented() { +void AbstractImageConverterTest::convertCompressed2DToDataNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToData(): feature advertised but not implemented\n"); + converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::exportCompressedToDataCustomDeleter() { +void AbstractImageConverterTest::convertCompressed2DToDataCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedData; } - Containers::Array doExportToData(const CompressedImageView2D&) override { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + Containers::Array doConvertToData(const CompressedImageView2D&) override { return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToData(): implementation is not allowed to use a custom Array deleter\n"); + converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); } /* Used by convertImageDataToData() and convertImageDataToFile() */ -class ImageDataConverter: public Trade::AbstractImageConverter { +class ImageData2DConverter: public Trade::AbstractImageConverter { private: - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData|ImageConverterFeature::ConvertCompressedData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData|ImageConverterFeature::ConvertCompressed2DToData; } - Containers::Array doExportToData(const ImageView2D&) override { + Containers::Array doConvertToData(const ImageView2D&) override { return Containers::array({'B'}); }; - Containers::Array doExportToData(const CompressedImageView2D&) override { + Containers::Array doConvertToData(const CompressedImageView2D&) override { return Containers::array({'C'}); }; }; -void AbstractImageConverterTest::exportImageDataToData() { - ImageDataConverter converter; +void AbstractImageConverterTest::convertImageData2DToData() { + ImageData2DConverter converter; - { - /* Should get "B" when converting uncompressed */ - ImageData2D image{PixelFormat::RGBA8Unorm, {}, nullptr}; - CORRADE_COMPARE_AS(converter.exportToData(image), - Containers::arrayView({'B'}), - TestSuite::Compare::Container); - } { - /* Should get "C" when converting compressed */ - ImageData2D image{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}; - CORRADE_COMPARE_AS(converter.exportToData(image), - Containers::arrayView({'C'}), - TestSuite::Compare::Container); - } + /* Should get "B" when converting uncompressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData2D{PixelFormat::RGBA8Unorm, {}, nullptr}), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + + /* Should get "C" when converting compressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData2D{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); } -void AbstractImageConverterTest::exportToFile() { +void AbstractImageConverterTest::convert2DToFile() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData; } - bool doExportToFile(const ImageView2D& image, const std::string& filename) override { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToFile; } + bool doConvertToFile(const ImageView2D& image, Containers::StringView filename) override { return Utility::Directory::write(filename, Containers::arrayView( {char(image.size().x()), char(image.size().y())})); } @@ -455,16 +491,16 @@ void AbstractImageConverterTest::exportToFile() { Utility::Directory::rm(filename); CORRADE_VERIFY(!Utility::Directory::exists(filename)); - CORRADE_VERIFY(converter.exportToFile(ImageView2D{PixelFormat::RGBA8Unorm, {0xf0, 0x0d}, {nullptr, 0xf0*0x0d*4}}, filename)); + CORRADE_VERIFY(converter.convertToFile(ImageView2D{PixelFormat::RGBA8Unorm, {0xf0, 0x0d}, {nullptr, 0xf0*0x0d*4}}, filename)); CORRADE_COMPARE_AS(filename, "\xf0\x0d", TestSuite::Compare::FileToString); } -void AbstractImageConverterTest::exportToFileThroughData() { +void AbstractImageConverterTest::convert2DToFileThroughData() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } - Containers::Array doExportToData(const ImageView2D& image) override { + Containers::Array doConvertToData(const ImageView2D& image) override { return Containers::array({char(image.size().x()), char(image.size().y())}); }; } converter; @@ -475,17 +511,17 @@ void AbstractImageConverterTest::exportToFileThroughData() { Utility::Directory::rm(filename); CORRADE_VERIFY(!Utility::Directory::exists(filename)); - /* doExportToFile() should call doExportToData() */ - CORRADE_VERIFY(converter.exportToFile(ImageView2D(PixelFormat::RGBA8Unorm, {0xfe, 0xed}, {nullptr, 0xfe*0xed*4}), filename)); + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(ImageView2D(PixelFormat::RGBA8Unorm, {0xfe, 0xed}, {nullptr, 0xfe*0xed*4}), filename)); CORRADE_COMPARE_AS(filename, "\xfe\xed", TestSuite::Compare::FileToString); } -void AbstractImageConverterTest::exportToFileThroughDataFailed() { +void AbstractImageConverterTest::convert2DToFileThroughDataFailed() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } - Containers::Array doExportToData(const ImageView2D&) override { + Containers::Array doConvertToData(const ImageView2D&) override { return {}; }; } converter; @@ -500,47 +536,47 @@ void AbstractImageConverterTest::exportToFileThroughDataFailed() { should be printed (the base implementation assumes the plugin does it) */ std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter.exportToFile(ImageView2D(PixelFormat::RGBA8Unorm, {0xfe, 0xed}, {nullptr, 0xfe*0xed*4}), filename)); + CORRADE_VERIFY(!converter.convertToFile(ImageView2D(PixelFormat::RGBA8Unorm, {0xfe, 0xed}, {nullptr, 0xfe*0xed*4}), filename)); CORRADE_VERIFY(!Utility::Directory::exists(filename)); CORRADE_COMPARE(out.str(), ""); } -void AbstractImageConverterTest::exportToFileThroughDataNotWritable() { +void AbstractImageConverterTest::convert2DToFileThroughDataNotWritable() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } - Containers::Array doExportToData(const ImageView2D& image) override { + Containers::Array doConvertToData(const ImageView2D& image) override { return Containers::array({char(image.size().x()), char(image.size().y())}); }; } converter; std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter.exportToFile(ImageView2D{PixelFormat::RGBA8Unorm, {0xfe, 0xed}, {nullptr, 0xfe*0xed*4}}, "/some/path/that/does/not/exist")); + CORRADE_VERIFY(!converter.convertToFile(ImageView2D{PixelFormat::RGBA8Unorm, {0xfe, 0xed}, {nullptr, 0xfe*0xed*4}}, "/some/path/that/does/not/exist")); CORRADE_COMPARE(out.str(), "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" - "Trade::AbstractImageConverter::exportToFile(): cannot write to file /some/path/that/does/not/exist\n"); + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); } -void AbstractImageConverterTest::exportToFileNotImplemented() { +void AbstractImageConverterTest::convert2DToFileNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertFile; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToFile; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToFile(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToFile(): feature advertised but not implemented\n"); + converter.convertToFile(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): 2D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::exportCompressedToFile() { +void AbstractImageConverterTest::convertCompressed2DToFile() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedFile; } - bool doExportToFile(const CompressedImageView2D& image, const std::string& filename) override { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToFile; } + bool doConvertToFile(const CompressedImageView2D& image, Containers::StringView filename) override { return Utility::Directory::write(filename, Containers::arrayView( {char(image.size().x()), char(image.size().y())})); } @@ -552,16 +588,16 @@ void AbstractImageConverterTest::exportCompressedToFile() { Utility::Directory::rm(filename); CORRADE_VERIFY(!Utility::Directory::exists(filename)); - CORRADE_VERIFY(converter.exportToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {0xd0, 0x0d}, {nullptr, 64}}, filename)); + CORRADE_VERIFY(converter.convertToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {0xd0, 0x0d}, {nullptr, 64}}, filename)); CORRADE_COMPARE_AS(filename, "\xd0\x0d", TestSuite::Compare::FileToString); } -void AbstractImageConverterTest::exportCompressedToFileThroughData() { +void AbstractImageConverterTest::convertCompressed2DToFileThroughData() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } - Containers::Array doExportToData(const CompressedImageView2D& image) override { + Containers::Array doConvertToData(const CompressedImageView2D& image) override { return Containers::array({char(image.size().x()), char(image.size().y())}); }; } converter; @@ -572,17 +608,17 @@ void AbstractImageConverterTest::exportCompressedToFileThroughData() { Utility::Directory::rm(filename); CORRADE_VERIFY(!Utility::Directory::exists(filename)); - /* doExportToFile() should call doExportToData() */ - CORRADE_VERIFY(converter.exportToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {0xb0, 0xd9}, {nullptr, 64}}, filename)); + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {0xb0, 0xd9}, {nullptr, 64}}, filename)); CORRADE_COMPARE_AS(filename, "\xb0\xd9", TestSuite::Compare::FileToString); } -void AbstractImageConverterTest::exportCompressedToFileThroughDataFailed() { +void AbstractImageConverterTest::convertCompressed2DToFileThroughDataFailed() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } - Containers::Array doExportToData(const CompressedImageView2D&) override { + Containers::Array doConvertToData(const CompressedImageView2D&) override { return {}; }; } converter; @@ -597,73 +633,69 @@ void AbstractImageConverterTest::exportCompressedToFileThroughDataFailed() { should be printed (the base implementation assumes the plugin does it) */ std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter.exportToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {0xb0, 0xd9}, {nullptr, 64}}, filename)); + CORRADE_VERIFY(!converter.convertToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {0xb0, 0xd9}, {nullptr, 64}}, filename)); CORRADE_VERIFY(!Utility::Directory::exists(filename)); CORRADE_COMPARE(out.str(), ""); } -void AbstractImageConverterTest::exportCompressedToFileThroughDataNotWritable() { +void AbstractImageConverterTest::convertCompressed2DToFileThroughDataNotWritable() { struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } - Containers::Array doExportToData(const CompressedImageView2D& image) override { + Containers::Array doConvertToData(const CompressedImageView2D& image) override { return Containers::array({char(image.size().x()), char(image.size().y())}); }; } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}, "/some/path/that/does/not/exist"); + converter.convertToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}, "/some/path/that/does/not/exist"); CORRADE_COMPARE(out.str(), "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" - "Trade::AbstractImageConverter::exportToFile(): cannot write to file /some/path/that/does/not/exist\n"); + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); } -void AbstractImageConverterTest::exportCompressedToFileNotImplemented() { +void AbstractImageConverterTest::convertCompressed2DToFileNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressedFile; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToFile; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.exportToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::exportToFile(): feature advertised but not implemented\n"); + converter.convertToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::exportImageDataToFile() { - ImageDataConverter converter; +void AbstractImageConverterTest::convertImageData2DToFile() { + ImageData2DConverter converter; - { - /* Should get "B" when converting uncompressed */ - ImageData2D image{PixelFormat::RGBA16F, {}, nullptr}; - CORRADE_VERIFY(converter.exportToFile(image, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); - CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), - "B", TestSuite::Compare::FileToString); - } { - /* Should get "C" when converting compressed */ - ImageData2D image{CompressedPixelFormat::Bc2RGBAUnorm, {}, nullptr}; - CORRADE_VERIFY(converter.exportToFile(image, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); - CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), - "C", TestSuite::Compare::FileToString); - } + /* Should get "B" when converting uncompressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData2D{PixelFormat::RGBA16F, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "B", TestSuite::Compare::FileToString); + + /* Should get "C" when converting compressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData2D{CompressedPixelFormat::Bc2RGBAUnorm, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "C", TestSuite::Compare::FileToString); } void AbstractImageConverterTest::debugFeature() { std::ostringstream out; - Debug{&out} << ImageConverterFeature::ConvertCompressedImage << ImageConverterFeature(0xf0); - CORRADE_COMPARE(out.str(), "Trade::ImageConverterFeature::ConvertCompressedImage Trade::ImageConverterFeature(0xf0)\n"); + Debug{&out} << ImageConverterFeature::ConvertCompressed2D << ImageConverterFeature(0xdeadbeef); + CORRADE_COMPARE(out.str(), "Trade::ImageConverterFeature::ConvertCompressed2D Trade::ImageConverterFeature(0xdeadbeef)\n"); } void AbstractImageConverterTest::debugFeatures() { std::ostringstream out; - Debug{&out} << (ImageConverterFeature::ConvertData|ImageConverterFeature::ConvertCompressedFile) << ImageConverterFeatures{}; - CORRADE_COMPARE(out.str(), "Trade::ImageConverterFeature::ConvertData|Trade::ImageConverterFeature::ConvertCompressedFile Trade::ImageConverterFeatures{}\n"); + Debug{&out} << (ImageConverterFeature::Convert2DToData|ImageConverterFeature::ConvertCompressed2DToFile) << ImageConverterFeatures{}; + CORRADE_COMPARE(out.str(), "Trade::ImageConverterFeature::Convert2DToData|Trade::ImageConverterFeature::ConvertCompressed2DToFile Trade::ImageConverterFeatures{}\n"); } void AbstractImageConverterTest::debugFlag() { diff --git a/src/Magnum/Trade/imageconverter.cpp b/src/Magnum/Trade/imageconverter.cpp index 27dc0001f..17a304e5a 100644 --- a/src/Magnum/Trade/imageconverter.cpp +++ b/src/Magnum/Trade/imageconverter.cpp @@ -332,7 +332,7 @@ key=true; configuration subgroups are delimited with /.)") Implementation::setOptions(*converter, args.value("converter-options")); /* Save output file */ - if(!converter->exportToFile(*image, output)) { + if(!converter->convertToFile(*image, output)) { Error() << "Cannot save file" << output; return 5; } diff --git a/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp b/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp index b25b90c55..c92cbae8a 100644 --- a/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp +++ b/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.cpp @@ -25,6 +25,8 @@ #include "AnyImageConverter.h" +#include +#include /* for Directory */ #include #include #include @@ -42,10 +44,10 @@ AnyImageConverter::AnyImageConverter(PluginManager::AbstractManager& manager, co AnyImageConverter::~AnyImageConverter() = default; ImageConverterFeatures AnyImageConverter::doFeatures() const { - return ImageConverterFeature::ConvertFile|ImageConverterFeature::ConvertCompressedFile; + return ImageConverterFeature::Convert2DToFile|ImageConverterFeature::ConvertCompressed2DToFile; } -bool AnyImageConverter::doExportToFile(const ImageView2D& image, const std::string& filename) { +bool AnyImageConverter::doConvertToFile(const ImageView2D& image, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); /** @todo lowercase only the extension, once Directory::split() is done */ @@ -73,18 +75,18 @@ bool AnyImageConverter::doExportToFile(const ImageView2D& image, const std::stri Utility::String::endsWith(normalized, ".vst")) plugin = "TgaImageConverter"; else { - Error{} << "Trade::AnyImageConverter::exportToFile(): cannot determine the format of" << filename; + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename; return false; } /* Try to load the plugin */ if(!(manager()->load(plugin) & PluginManager::LoadState::Loaded)) { - Error{} << "Trade::AnyImageConverter::exportToFile(): cannot load the" << plugin << "plugin"; + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot load the" << plugin << "plugin"; return false; } if(flags() & ImageConverterFlag::Verbose) { Debug d; - d << "Trade::AnyImageConverter::exportToFile(): using" << plugin; + d << "Trade::AnyImageConverter::convertToFile(): using" << plugin; PluginManager::PluginMetadata* metadata = manager()->metadata(plugin); CORRADE_INTERNAL_ASSERT(metadata); if(plugin != metadata->name()) @@ -97,19 +99,19 @@ bool AnyImageConverter::doExportToFile(const ImageView2D& image, const std::stri /* Try to convert the file (error output should be printed by the plugin itself) */ - return converter->exportToFile(image, filename); + return converter->convertToFile(image, filename); } -bool AnyImageConverter::doExportToFile(const CompressedImageView2D&, const std::string& filename) { +bool AnyImageConverter::doConvertToFile(const CompressedImageView2D&, const Containers::StringView filename) { CORRADE_INTERNAL_ASSERT(manager()); /* No file formats to store compressed data yet */ - Error{} << "Trade::AnyImageConverter::exportToFile(): cannot determine the format of" << filename << "to store compressed data"; + Error{} << "Trade::AnyImageConverter::convertToFile(): cannot determine the format of" << filename << "to store compressed data"; return false; } }} CORRADE_PLUGIN_REGISTER(AnyImageConverter, Magnum::Trade::AnyImageConverter, - "cz.mosra.magnum.Trade.AbstractImageConverter/0.2.1") + "cz.mosra.magnum.Trade.AbstractImageConverter/0.3") diff --git a/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.h b/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.h index d37fa26da..c2133b902 100644 --- a/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.h +++ b/src/MagnumPlugins/AnyImageConverter/AnyImageConverter.h @@ -117,8 +117,8 @@ class MAGNUM_ANYIMAGECONVERTER_EXPORT AnyImageConverter: public AbstractImageCon private: MAGNUM_ANYIMAGECONVERTER_LOCAL ImageConverterFeatures doFeatures() const override; - MAGNUM_ANYIMAGECONVERTER_LOCAL bool doExportToFile(const ImageView2D& image, const std::string& filename) override; - MAGNUM_ANYIMAGECONVERTER_LOCAL bool doExportToFile(const CompressedImageView2D& image, const std::string& filename) override; + MAGNUM_ANYIMAGECONVERTER_LOCAL bool doConvertToFile(const ImageView2D& image, Containers::StringView filename) override; + MAGNUM_ANYIMAGECONVERTER_LOCAL bool doConvertToFile(const CompressedImageView2D& image, Containers::StringView filename) override; }; }} diff --git a/src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp b/src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp index 11be20553..6bf445a5c 100644 --- a/src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp +++ b/src/MagnumPlugins/AnyImageConverter/Test/AnyImageConverterTest.cpp @@ -24,6 +24,7 @@ */ #include +#include #include #include #include @@ -121,7 +122,7 @@ void AnyImageConverterTest::convert() { /* Just test that the exported file exists */ Containers::Pointer converter = _manager.instantiate("AnyImageConverter"); - CORRADE_VERIFY(converter->exportToFile(Image, filename)); + CORRADE_VERIFY(converter->convertToFile(Image, filename)); CORRADE_VERIFY(Utility::Directory::exists(filename)); } @@ -133,14 +134,14 @@ void AnyImageConverterTest::detect() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!converter->exportToFile(Image, data.filename)); + CORRADE_VERIFY(!converter->convertToFile(Image, data.filename)); /* Can't use raw string literals in macros on GCC 4.8 */ #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\nTrade::AnyImageConverter::exportToFile(): cannot load the {0} plugin\n", data.plugin)); +"PluginManager::Manager::load(): plugin {0} is not static and was not found in nonexistent\nTrade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n", data.plugin)); #else CORRADE_COMPARE(out.str(), Utility::formatString( -"PluginManager::Manager::load(): plugin {0} was not found\nTrade::AnyImageConverter::exportToFile(): cannot load the {0} plugin\n", data.plugin)); +"PluginManager::Manager::load(): plugin {0} was not found\nTrade::AnyImageConverter::convertToFile(): cannot load the {0} plugin\n", data.plugin)); #endif } @@ -149,9 +150,9 @@ void AnyImageConverterTest::unknown() { Error redirectError{&output}; Containers::Pointer converter = _manager.instantiate("AnyImageConverter"); - CORRADE_VERIFY(!converter->exportToFile(Image, "image.xcf")); + CORRADE_VERIFY(!converter->convertToFile(Image, "image.xcf")); - CORRADE_COMPARE(output.str(), "Trade::AnyImageConverter::exportToFile(): cannot determine the format of image.xcf\n"); + CORRADE_COMPARE(output.str(), "Trade::AnyImageConverter::convertToFile(): cannot determine the format of image.xcf\n"); } void AnyImageConverterTest::verbose() { @@ -169,12 +170,12 @@ void AnyImageConverterTest::verbose() { std::ostringstream out; { Debug redirectOutput{&out}; - CORRADE_VERIFY(converter->exportToFile(Image, filename)); + CORRADE_VERIFY(converter->convertToFile(Image, filename)); } CORRADE_VERIFY(Utility::Directory::exists(filename)); CORRADE_COMPARE(out.str(), - "Trade::AnyImageConverter::exportToFile(): using TgaImageConverter\n" - "Trade::TgaImageConverter::exportToData(): converting from RGB to BGR\n"); + "Trade::AnyImageConverter::convertToFile(): using TgaImageConverter\n" + "Trade::TgaImageConverter::convertToData(): converting from RGB to BGR\n"); } }}}} diff --git a/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp b/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp index eb0c2dfdb..c9078ceb1 100644 --- a/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp +++ b/src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp @@ -120,7 +120,7 @@ std::vector>> MagnumFontConverter std::copy(confStr.begin(), confStr.end(), confData.begin()); /* Save cache image */ - auto tgaData = Trade::TgaImageConverter().exportToData(cache.image()); + auto tgaData = Trade::TgaImageConverter().convertToData(cache.image()); std::vector>> out; out.emplace_back(filename + ".conf", std::move(confData)); diff --git a/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp b/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp index 5ea5b0706..b7fc615a8 100644 --- a/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp +++ b/src/MagnumPlugins/TgaImageConverter/Test/TgaImageConverterTest.cpp @@ -63,8 +63,8 @@ constexpr struct { } VerboseData[] { {"", {}, "", ""}, {"verbose", ImageConverterFlag::Verbose, - "Trade::TgaImageConverter::exportToData(): converting from RGB to BGR\n", - "Trade::TgaImageConverter::exportToData(): converting from RGBA to BGRA\n"} + "Trade::TgaImageConverter::convertToData(): converting from RGB to BGR\n", + "Trade::TgaImageConverter::convertToData(): converting from RGBA to BGRA\n"} }; /* Padded to four byte alignment (the resulting file is *not* padded) */ @@ -118,9 +118,9 @@ void TgaImageConverterTest::wrongFormat() { Error redirectError{&out}; Containers::Pointer converter = _converterManager.instantiate("TgaImageConverter"); - const auto data = converter->exportToData(image); + const auto data = converter->convertToData(image); CORRADE_VERIFY(!data); - CORRADE_COMPARE(out.str(), "Trade::TgaImageConverter::exportToData(): unsupported pixel format PixelFormat::RG8Unorm\n"); + CORRADE_COMPARE(out.str(), "Trade::TgaImageConverter::convertToData(): unsupported pixel format PixelFormat::RG8Unorm\n"); } void TgaImageConverterTest::rgb() { @@ -134,7 +134,7 @@ void TgaImageConverterTest::rgb() { Containers::Array array; { Debug redirectOutput{&out}; - array = converter->exportToData(OriginalRGB); + array = converter->convertToData(OriginalRGB); } CORRADE_VERIFY(out); @@ -165,7 +165,7 @@ void TgaImageConverterTest::rgba() { Containers::Array array; { Debug redirectOutput{&out}; - array = converter->exportToData(OriginalRGBA); + array = converter->convertToData(OriginalRGBA); } CORRADE_VERIFY(out); diff --git a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp index da34778fc..ca1a4e3c1 100644 --- a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp +++ b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp @@ -43,9 +43,9 @@ TgaImageConverter::TgaImageConverter() = default; TgaImageConverter::TgaImageConverter(PluginManager::AbstractManager& manager, const std::string& plugin): AbstractImageConverter{manager, plugin} {} -ImageConverterFeatures TgaImageConverter::doFeatures() const { return ImageConverterFeature::ConvertData; } +ImageConverterFeatures TgaImageConverter::doFeatures() const { return ImageConverterFeature::Convert2DToData; } -Containers::Array TgaImageConverter::doExportToData(const ImageView2D& image) { +Containers::Array TgaImageConverter::doConvertToData(const ImageView2D& image) { /* Initialize data buffer */ const auto pixelSize = UnsignedByte(image.pixelSize()); Containers::Array data{Containers::ValueInit, sizeof(Implementation::TgaHeader) + pixelSize*image.size().product()}; @@ -61,7 +61,7 @@ Containers::Array TgaImageConverter::doExportToData(const ImageView2D& ima header->imageType = 3; break; default: - Error() << "Trade::TgaImageConverter::exportToData(): unsupported pixel format" << image.format(); + Error() << "Trade::TgaImageConverter::convertToData(): unsupported pixel format" << image.format(); return nullptr; } header->bpp = pixelSize*8; @@ -75,12 +75,12 @@ Containers::Array TgaImageConverter::doExportToData(const ImageView2D& ima if(image.format() == PixelFormat::RGB8Unorm) { if(flags() & ImageConverterFlag::Verbose) - Debug{} << "Trade::TgaImageConverter::exportToData(): converting from RGB to BGR"; + Debug{} << "Trade::TgaImageConverter::convertToData(): converting from RGB to BGR"; for(Vector3ub& pixel: Containers::arrayCast(pixels)) pixel = Math::gather<'b', 'g', 'r'>(pixel); } else if(image.format() == PixelFormat::RGBA8Unorm) { if(flags() & ImageConverterFlag::Verbose) - Debug{} << "Trade::TgaImageConverter::exportToData(): converting from RGBA to BGRA"; + Debug{} << "Trade::TgaImageConverter::convertToData(): converting from RGBA to BGRA"; for(Vector4ub& pixel: Containers::arrayCast(pixels)) pixel = Math::gather<'b', 'g', 'r', 'a'>(pixel); } @@ -91,4 +91,4 @@ Containers::Array TgaImageConverter::doExportToData(const ImageView2D& ima }} CORRADE_PLUGIN_REGISTER(TgaImageConverter, Magnum::Trade::TgaImageConverter, - "cz.mosra.magnum.Trade.AbstractImageConverter/0.2.1") + "cz.mosra.magnum.Trade.AbstractImageConverter/0.3") diff --git a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.h b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.h index be3ebc6cd..8c88cad0e 100644 --- a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.h +++ b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.h @@ -104,7 +104,7 @@ class MAGNUM_TGAIMAGECONVERTER_EXPORT TgaImageConverter: public AbstractImageCon private: ImageConverterFeatures MAGNUM_TGAIMAGECONVERTER_LOCAL doFeatures() const override; - Containers::Array MAGNUM_TGAIMAGECONVERTER_LOCAL doExportToData(const ImageView2D& image) override; + Containers::Array MAGNUM_TGAIMAGECONVERTER_LOCAL doConvertToData(const ImageView2D& image) override; }; }} From 2ce125a1b3e3d6a5a9370dc0eefab72fd465b39d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 20:51:47 +0200 Subject: [PATCH 126/161] Trade: doc++ --- src/Magnum/Trade/AbstractImageConverter.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index a8db45c57..a49ed123c 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -549,6 +549,7 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract /** * @brief Implementation for @ref setFlags() + * @m_since{2020,06} * * Useful when the converter needs to modify some internal state on * flag setup. Default implementation does nothing and this From 2df2a4700704b0d4ed4aa9ebe0e0b16705e4ff35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 8 Apr 2021 20:50:52 +0200 Subject: [PATCH 127/161] Trade: support 1D and 3D images in AbstractImageConverter. I wanted just 3D at first, but then thought why not do 1D as well. Lots of dry copypasted code, nothing interesting to see here. --- doc/changelog.dox | 1 + src/Magnum/Trade/AbstractImageConverter.cpp | 242 +++- src/Magnum/Trade/AbstractImageConverter.h | 422 ++++++- .../Trade/Test/AbstractImageConverterTest.cpp | 1102 ++++++++++++++++- 4 files changed, 1723 insertions(+), 44 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index a797692ca..80f29afce 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -179,6 +179,7 @@ See also: - New @ref Trade::SkinData class and @ref Trade::AbstractImporter::skin2D() / @ref Trade::AbstractImporter::skin3D() family of APIs for skin import, as well as support in @ref Trade::AnySceneImporter "AnySceneImporter" +- 1D and 3D image support in @ref Trade::AbstractImageConverter - @ref Trade::LightData got extended to support light attenuation and range parameters as well and spot light inner and outer angle - @ref Trade::AbstractImporter, @ref Trade::AbstractImageConverter and diff --git a/src/Magnum/Trade/AbstractImageConverter.cpp b/src/Magnum/Trade/AbstractImageConverter.cpp index fc01a90b3..b1bf51373 100644 --- a/src/Magnum/Trade/AbstractImageConverter.cpp +++ b/src/Magnum/Trade/AbstractImageConverter.cpp @@ -95,6 +95,19 @@ void AbstractImageConverter::clearFlags(ImageConverterFlags flags) { setFlags(_flags & ~flags); } +Containers::Optional AbstractImageConverter::convert(const ImageView1D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert1D, + "Trade::AbstractImageConverter::convert(): 1D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Optional AbstractImageConverter::doConvert(const ImageView1D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): 1D image conversion advertised but not implemented", {}); +} + Containers::Optional AbstractImageConverter::convert(const ImageView2D& image) { CORRADE_ASSERT(features() & ImageConverterFeature::Convert2D, "Trade::AbstractImageConverter::convert(): 2D image conversion not supported", {}); @@ -140,6 +153,32 @@ Containers::Optional AbstractImageConverter::exportToCompress } #endif +Containers::Optional AbstractImageConverter::convert(const ImageView3D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert3D, + "Trade::AbstractImageConverter::convert(): 3D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Optional AbstractImageConverter::doConvert(const ImageView3D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): 3D image conversion advertised but not implemented", {}); +} + +Containers::Optional AbstractImageConverter::convert(const CompressedImageView1D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed1D, + "Trade::AbstractImageConverter::convert(): compressed 1D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Optional AbstractImageConverter::doConvert(const CompressedImageView1D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): compressed 1D image conversion advertised but not implemented", {}); +} + Containers::Optional AbstractImageConverter::convert(const CompressedImageView2D& image) { CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2D, "Trade::AbstractImageConverter::convert(): compressed 2D image conversion not supported", {}); @@ -153,10 +192,44 @@ Containers::Optional AbstractImageConverter::doConvert(const Compre CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): compressed 2D image conversion advertised but not implemented", {}); } +Containers::Optional AbstractImageConverter::convert(const CompressedImageView3D& image) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed3D, + "Trade::AbstractImageConverter::convert(): compressed 3D image conversion not supported", {}); + + Containers::Optional out = doConvert(image); + CORRADE_ASSERT(!out || !out->_data.deleter(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Optional AbstractImageConverter::doConvert(const CompressedImageView3D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convert(): compressed 3D image conversion advertised but not implemented", {}); +} + +Containers::Optional AbstractImageConverter::convert(const ImageData1D& image) { + return image.isCompressed() ? convert(CompressedImageView1D(image)) : convert(ImageView1D(image)); +} + Containers::Optional AbstractImageConverter::convert(const ImageData2D& image) { return image.isCompressed() ? convert(CompressedImageView2D(image)) : convert(ImageView2D(image)); } +Containers::Optional AbstractImageConverter::convert(const ImageData3D& image) { + return image.isCompressed() ? convert(CompressedImageView3D(image)) : convert(ImageView3D(image)); +} + +Containers::Array AbstractImageConverter::convertToData(const ImageView1D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert1DToData, + "Trade::AbstractImageConverter::convertToData(): 1D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Array AbstractImageConverter::doConvertToData(const ImageView1D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): 1D image conversion advertised but not implemented", nullptr); +} + Containers::Array AbstractImageConverter::convertToData(const ImageView2D& image) { CORRADE_ASSERT(features() >= ImageConverterFeature::Convert2DToData, "Trade::AbstractImageConverter::convertToData(): 2D image conversion not supported", nullptr); @@ -176,6 +249,32 @@ Containers::Array AbstractImageConverter::exportToData(const ImageView2D& } #endif +Containers::Array AbstractImageConverter::convertToData(const ImageView3D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert3DToData, + "Trade::AbstractImageConverter::convertToData(): 3D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Array AbstractImageConverter::doConvertToData(const ImageView3D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): 3D image conversion advertised but not implemented", nullptr); +} + +Containers::Array AbstractImageConverter::convertToData(const CompressedImageView1D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed1DToData, + "Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Array AbstractImageConverter::doConvertToData(const CompressedImageView1D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion advertised but not implemented", nullptr); +} + Containers::Array AbstractImageConverter::convertToData(const CompressedImageView2D& image) { CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed2DToData, "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion not supported", nullptr); @@ -195,6 +294,23 @@ Containers::Array AbstractImageConverter::exportToData(const CompressedIma } #endif +Containers::Array AbstractImageConverter::convertToData(const CompressedImageView3D& image) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed3DToData, + "Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion not supported", nullptr); + + Containers::Array out = doConvertToData(image); + CORRADE_ASSERT(!out.deleter(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter", {}); + return out; +} + +Containers::Array AbstractImageConverter::doConvertToData(const CompressedImageView3D&) { + CORRADE_ASSERT_UNREACHABLE("Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion advertised but not implemented", nullptr); +} + +Containers::Array AbstractImageConverter::convertToData(const ImageData1D& image) { + return image.isCompressed() ? convertToData(CompressedImageView1D(image)) : convertToData(ImageView1D(image)); +} + Containers::Array AbstractImageConverter::convertToData(const ImageData2D& image) { return image.isCompressed() ? convertToData(CompressedImageView2D(image)) : convertToData(ImageView2D(image)); } @@ -205,6 +321,32 @@ Containers::Array AbstractImageConverter::exportToData(const ImageData2D& } #endif +Containers::Array AbstractImageConverter::convertToData(const ImageData3D& image) { + return image.isCompressed() ? convertToData(CompressedImageView3D(image)) : convertToData(ImageView3D(image)); +} + +bool AbstractImageConverter::convertToFile(const ImageView1D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert1DToFile, + "Trade::AbstractImageConverter::convertToFile(): 1D image conversion not supported", {}); + + return doConvertToFile(image, filename); +} + +bool AbstractImageConverter::doConvertToFile(const ImageView1D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert1DToData, "Trade::AbstractImageConverter::convertToFile(): 1D image conversion advertised but not implemented", false); + + const auto data = doConvertToData(image); + /* No deleter checks as it doesn't matter here */ + if(!data) return false; + + if(!Utility::Directory::write(filename, data)) { + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; + return false; + } + + return true; +} + bool AbstractImageConverter::convertToFile(const ImageView2D& image, const Containers::StringView filename) { CORRADE_ASSERT(features() & ImageConverterFeature::Convert2DToFile, "Trade::AbstractImageConverter::convertToFile(): 2D image conversion not supported", {}); @@ -233,6 +375,50 @@ bool AbstractImageConverter::exportToFile(const ImageView2D& image, const std::s } #endif +bool AbstractImageConverter::convertToFile(const ImageView3D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::Convert3DToFile, + "Trade::AbstractImageConverter::convertToFile(): 3D image conversion not supported", {}); + + return doConvertToFile(image, filename); +} + +bool AbstractImageConverter::doConvertToFile(const ImageView3D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::Convert3DToData, "Trade::AbstractImageConverter::convertToFile(): 3D image conversion advertised but not implemented", false); + + const auto data = doConvertToData(image); + /* No deleter checks as it doesn't matter here */ + if(!data) return false; + + if(!Utility::Directory::write(filename, data)) { + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; + return false; + } + + return true; +} + +bool AbstractImageConverter::convertToFile(const CompressedImageView1D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed1DToFile, + "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion not supported", {}); + + return doConvertToFile(image, filename); +} + +bool AbstractImageConverter::doConvertToFile(const CompressedImageView1D& image, Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed1DToData, "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion advertised but not implemented", false); + + const auto data = doConvertToData(image); + /* No deleter checks as it doesn't matter here */ + if(!data) return false; + + if(!Utility::Directory::write(filename, data)) { + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; + return false; + } + + return true; +} + bool AbstractImageConverter::convertToFile(const CompressedImageView2D& image, const Containers::StringView filename) { CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed2DToFile, "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported", {}); @@ -261,6 +447,32 @@ bool AbstractImageConverter::exportToFile(const CompressedImageView2D& image, co } #endif +bool AbstractImageConverter::convertToFile(const CompressedImageView3D& image, const Containers::StringView filename) { + CORRADE_ASSERT(features() & ImageConverterFeature::ConvertCompressed3DToFile, + "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion not supported", {}); + + return doConvertToFile(image, filename); +} + +bool AbstractImageConverter::doConvertToFile(const CompressedImageView3D& image, Containers::StringView filename) { + CORRADE_ASSERT(features() >= ImageConverterFeature::ConvertCompressed3DToData, "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion advertised but not implemented", false); + + const auto data = doConvertToData(image); + /* No deleter checks as it doesn't matter here */ + if(!data) return false; + + if(!Utility::Directory::write(filename, data)) { + Error() << "Trade::AbstractImageConverter::convertToFile(): cannot write to file" << filename; + return false; + } + + return true; +} + +bool AbstractImageConverter::convertToFile(const ImageData1D& image, const Containers::StringView filename) { + return image.isCompressed() ? convertToFile(CompressedImageView1D(image), filename) : convertToFile(ImageView1D(image), filename); +} + bool AbstractImageConverter::convertToFile(const ImageData2D& image, const Containers::StringView filename) { return image.isCompressed() ? convertToFile(CompressedImageView2D(image), filename) : convertToFile(ImageView2D(image), filename); } @@ -271,18 +483,34 @@ bool AbstractImageConverter::exportToFile(const ImageData2D& image, const std::s } #endif +bool AbstractImageConverter::convertToFile(const ImageData3D& image, const Containers::StringView filename) { + return image.isCompressed() ? convertToFile(CompressedImageView3D(image), filename) : convertToFile(ImageView3D(image), filename); +} + Debug& operator<<(Debug& debug, const ImageConverterFeature value) { debug << "Trade::ImageConverterFeature" << Debug::nospace; switch(value) { /* LCOV_EXCL_START */ #define _c(v) case ImageConverterFeature::v: return debug << "::" #v; + _c(Convert1D) _c(Convert2D) + _c(Convert3D) + _c(ConvertCompressed1D) _c(ConvertCompressed2D) + _c(ConvertCompressed3D) + _c(Convert1DToFile) _c(Convert2DToFile) + _c(Convert3DToFile) + _c(ConvertCompressed1DToFile) _c(ConvertCompressed2DToFile) + _c(ConvertCompressed3DToFile) + _c(Convert1DToData) _c(Convert2DToData) + _c(Convert3DToData) + _c(ConvertCompressed1DToData) _c(ConvertCompressed2DToData) + _c(ConvertCompressed3DToData) #undef _c /* LCOV_EXCL_STOP */ } @@ -292,13 +520,25 @@ Debug& operator<<(Debug& debug, const ImageConverterFeature value) { Debug& operator<<(Debug& debug, const ImageConverterFeatures value) { return Containers::enumSetDebugOutput(debug, value, "Trade::ImageConverterFeatures{}", { + ImageConverterFeature::Convert1D, ImageConverterFeature::Convert2D, + ImageConverterFeature::Convert3D, + ImageConverterFeature::ConvertCompressed1D, ImageConverterFeature::ConvertCompressed2D, + ImageConverterFeature::ConvertCompressed3D, + ImageConverterFeature::Convert1DToData, ImageConverterFeature::Convert2DToData, + ImageConverterFeature::Convert3DToData, + ImageConverterFeature::ConvertCompressed1DToData, ImageConverterFeature::ConvertCompressed2DToData, + ImageConverterFeature::ConvertCompressed3DToData, /* These are implied by Convert[Compressed]ToData, so have to be last */ + ImageConverterFeature::Convert1DToFile, ImageConverterFeature::Convert2DToFile, - ImageConverterFeature::ConvertCompressed2DToFile}); + ImageConverterFeature::Convert3DToFile, + ImageConverterFeature::ConvertCompressed1DToFile, + ImageConverterFeature::ConvertCompressed2DToFile, + ImageConverterFeature::ConvertCompressed3DToFile}); } Debug& operator<<(Debug& debug, const ImageConverterFlag value) { diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index a49ed123c..02a147d6a 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -44,12 +44,19 @@ namespace Magnum { namespace Trade { @see @ref ImageConverterFeatures, @ref AbstractImageConverter::features() */ enum class ImageConverterFeature: UnsignedInt { + /** + * Convert a 1D image with + * @ref AbstractImageConverter::convert(const ImageView1D&) + * @m_since_latest + */ + Convert1D = 1 << 0, + /** * Convert a 2D image with * @ref AbstractImageConverter::convert(const ImageView2D&) * @m_since_latest */ - Convert2D = 1 << 0, + Convert2D = 1 << 1, #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -71,19 +78,47 @@ enum class ImageConverterFeature: UnsignedInt { ConvertCompressedImage CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2D instead") = Convert2D, #endif + /** + * Convert a 3D image with + * @ref AbstractImageConverter::convert(const ImageView3D&) + * @m_since_latest + */ + Convert3D = 1 << 3, + + /** + * Convert a compressed 1D image with + * @ref AbstractImageConverter::convert(const CompressedImageView1D&) + * @m_since_latest + */ + ConvertCompressed1D = 1 << 4, + /** * Convert a compressed 2D image with * @ref AbstractImageConverter::convert(const CompressedImageView2D&) * @m_since_latest */ - ConvertCompressed2D = 1 << 1, + ConvertCompressed2D = 1 << 5, + + /** + * Convert a compressed 3D image with + * @ref AbstractImageConverter::convert(const CompressedImageView3D&) + * @m_since_latest + */ + ConvertCompressed3D = 1 << 6, + + /** + * Convert a 1D image to a file with + * @ref AbstractImageConverter::convertToFile(const ImageView1D&, Containers::StringView) + * @m_since_latest + */ + Convert1DToFile = 1 << 7, /** * Convert a 2D image to a file with * @ref AbstractImageConverter::convertToFile(const ImageView2D&, Containers::StringView) * @m_since_latest */ - Convert2DToFile = 1 << 2, + Convert2DToFile = 1 << 8, #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -94,12 +129,26 @@ enum class ImageConverterFeature: UnsignedInt { ConvertFile CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2DToFile instead") = Convert2DToFile, #endif + /** + * Convert a 3D image to a file with + * @ref AbstractImageConverter::convertToFile(const ImageView3D&, Containers::StringView) + * @m_since_latest + */ + Convert3DToFile = 1 << 9, + + /** + * Convert a compressed 1D image to a file with + * @ref AbstractImageConverter::convertToFile(const CompressedImageView1D&, Containers::StringView) + * @m_since_latest + */ + ConvertCompressed1DToFile = 1 << 10, + /** * Convert a compressed 2D image to a file with * @ref AbstractImageConverter::convertToFile(const CompressedImageView2D&, Containers::StringView) * @m_since_latest */ - ConvertCompressed2DToFile = 1 << 3, + ConvertCompressed2DToFile = 1 << 11, #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -110,13 +159,28 @@ enum class ImageConverterFeature: UnsignedInt { ConvertCompressedFile CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::ConvertCompressed2DToFile instead") = ConvertCompressed2DToFile, #endif + /** + * Convert a compressed 3D image to a file with + * @ref AbstractImageConverter::convertToFile(const CompressedImageView3D&, Containers::StringView) + * @m_since_latest + */ + ConvertCompressed3DToFile = 1 << 12, + + /** + * Convert a 1D image to raw data with + * @ref AbstractImageConverter::convertToData(const ImageView1D&). + * Implies @ref ImageConverterFeature::Convert1DToFile. + * @m_since_latest + */ + Convert1DToData = Convert1DToFile|(1 << 13), + /** * Convert a 2D image to raw data with * @ref AbstractImageConverter::convertToData(const ImageView2D&). * Implies @ref ImageConverterFeature::Convert2DToFile. * @m_since_latest */ - Convert2DToData = Convert2DToFile|(1 << 4), + Convert2DToData = Convert2DToFile|(1 << 13), #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -127,13 +191,29 @@ enum class ImageConverterFeature: UnsignedInt { ConvertData CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::Convert2DToData instead") = Convert2DToData, #endif + /** + * Convert a 3D image to raw data with + * @ref AbstractImageConverter::convertToData(const ImageView3D&). + * Implies @ref ImageConverterFeature::Convert3DToFile. + * @m_since_latest + */ + Convert3DToData = Convert3DToFile|(1 << 13), + + /** + * Convert a compressed 1D image to raw data with + * @ref AbstractImageConverter::convertToData(const CompressedImageView1D&). + * Implies @ref ImageConverterFeature::ConvertCompressed1DToFile. + * @m_since_latest + */ + ConvertCompressed1DToData = ConvertCompressed1DToFile|(1 << 13), + /** * Convert a compressed 2D image to raw data with * @ref AbstractImageConverter::convertToData(const CompressedImageView2D&). * Implies @ref ImageConverterFeature::ConvertCompressed2DToFile. * @m_since_latest */ - ConvertCompressed2DToData = ConvertCompressed2DToFile|(1 << 4), + ConvertCompressed2DToData = ConvertCompressed2DToFile|(1 << 13), #ifdef MAGNUM_BUILD_DEPRECATED /** @@ -143,6 +223,14 @@ enum class ImageConverterFeature: UnsignedInt { */ ConvertCompressedData CORRADE_DEPRECATED_ENUM("use ImageConverterFeature::ConvertCompressed2DToData instead") = ConvertCompressed2DToData, #endif + + /** + * Convert a compressed 3D image to raw data with + * @ref AbstractImageConverter::convertToData(const CompressedImageView3D&). + * Implies @ref ImageConverterFeature::ConvertCompressed3DToFile. + * @m_since_latest + */ + ConvertCompressed3DToData = ConvertCompressed3DToFile|(1 << 13) }; /** @@ -353,6 +441,21 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ void clearFlags(ImageConverterFlags flags); + /** + * @brief Convert a 1D image + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert1D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const CompressedImageView1D&), + * @ref convert(const ImageData1D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() + */ + Containers::Optional convert(const ImageView1D& image); + /** * @brief Convert a 2D image * @m_since_latest @@ -384,6 +487,36 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convert(const ImageView2D&) instead") Containers::Optional exportToCompressedImage(const ImageView2D& image); #endif + /** + * @brief Convert a 3D image + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert3D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const CompressedImageView3D&), + * @ref convert(const ImageData3D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() + */ + Containers::Optional convert(const ImageView3D& image); + + /** + * @brief Convert a compressed 1D image + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed1D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const ImageView1D&), + * @ref convert(const ImageData1D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() + */ + Containers::Optional convert(const CompressedImageView1D& image); + /** * @brief Convert a compressed 2D image * @m_since_latest @@ -399,6 +532,33 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ Containers::Optional convert(const CompressedImageView2D& image); + /** + * @brief Convert a compressed 3D image + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed3D is + * supported. Returns converted image on success, + * @ref Containers::NullOpt otherwise. The implementation is allowed to + * return both a compressed an an uncompressed image, see documentation + * of a particular converter for more information. + * @see @ref features(), @ref convert(const ImageView3D&), + * @ref convert(const ImageData3D&), @ref convertToData(), + * @ref convertToFile(), @ref ImageData::isCompressed() + */ + Containers::Optional convert(const CompressedImageView3D& image); + + /** + * @brief Convert a 1D image data + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convert(const ImageView1D&) or + * @ref convert(const CompressedImageView1D&). See documentation of + * these two functions for details. + * @see @ref ImageData::isCompressed() + */ + Containers::Optional convert(const ImageData1D& image); + /** * @brief Convert a 2D image data * @m_since_latest @@ -411,6 +571,30 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ Containers::Optional convert(const ImageData2D& image); + /** + * @brief Convert a 3D image data + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convert(const ImageView3D&) or + * @ref convert(const CompressedImageView3D&). See documentation of + * these two functions for details. + * @see @ref ImageData::isCompressed() + */ + Containers::Optional convert(const ImageData3D& image); + + /** + * @brief Convert a 1D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert1DToData is + * supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const CompressedImageView1D&), + * @ref convertToData(const ImageData1D&), @ref convert(), + * @ref convertToFile() + */ + Containers::Array convertToData(const ImageView1D& image); + /** * @brief Convert a 2D image to a raw data * @m_since_latest @@ -432,6 +616,30 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToData(const ImageView2D&) instead") Containers::Array exportToData(const ImageView2D& image); #endif + /** + * @brief Convert a 3D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert3DToData is + * supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const CompressedImageView3D&), + * @ref convertToData(const ImageData3D&), @ref convert(), + * @ref convertToFile() + */ + Containers::Array convertToData(const ImageView3D& image); + + /** + * @brief Convert a compressed 1D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed1DToData + * is supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const ImageView1D&), + * @ref convertToData(const ImageData1D&), @ref convert(), + * @ref convertToFile() + */ + Containers::Array convertToData(const CompressedImageView1D& image); + /** * @brief Convert a compressed 2D image to a raw data * @m_since_latest @@ -453,6 +661,30 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToData(const CompressedImageView2D&) instead") Containers::Array exportToData(const CompressedImageView2D& image); #endif + /** + * @brief Convert a compressed 3D image to a raw data + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed3DToData + * is supported. Returns data on success, @cpp nullptr @ce otherwise. + * @see @ref features(), @ref convertToData(const ImageView3D&), + * @ref convertToData(const ImageData3D&), @ref convert() + * @ref convertToFile() + */ + Containers::Array convertToData(const CompressedImageView3D& image); + + /** + * @brief Convert a 1D image data to a raw data + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convertToData(const ImageView1D&) or + * @ref convertToData(const CompressedImageView1D&). See documentation + * of these two functions for details. + * @see @ref ImageData::isCompressed() + */ + Containers::Array convertToData(const ImageData1D& image); + /** * @brief Convert a 2D image data to a raw data * @m_since_latest @@ -474,6 +706,31 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToData(const ImageView2D&) instead") Containers::Array exportToData(const ImageData2D& image); #endif + /** + * @brief Convert a 3D image data to a raw data + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convertToData(const ImageView3D&) or + * @ref convertToData(const CompressedImageView3D&). See documentation + * of these two functions for details. + * @see @ref ImageData::isCompressed() + */ + Containers::Array convertToData(const ImageData3D& image); + + /** + * @brief Convert a 1D image to a file + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert1DToFile or + * @ref ImageConverterFeature::Convert1DToData is supported. Returns + * @cpp true @ce on success, @cpp false @ce otherwise. + * @see @ref features(), @ref convertToFile(const CompressedImageView1D&, Containers::StringView), + * @ref convertToFile(const ImageData1D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const ImageView1D& image, Containers::StringView filename); + /** * @brief Convert a 2D image to a file * @m_since_latest @@ -497,6 +754,33 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToFile(const ImageView2D&, Containers::StringView) instead") bool exportToFile(const ImageView2D& image, const std::string& filename); #endif + /** + * @brief Convert a 3D image to a file + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::Convert3DToFile or + * @ref ImageConverterFeature::Convert3DToData is supported. Returns + * @cpp true @ce on success, @cpp false @ce otherwise. + * @see @ref features(), @ref convertToFile(const CompressedImageView3D&, Containers::StringView), + * @ref convertToFile(const ImageData3D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const ImageView3D& image, Containers::StringView filename); + + /** + * @brief Convert a compressed 1D image to a file + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed1DToFile + * or @ref ImageConverterFeature::ConvertCompressed1DToData is + * supported. Returns @cpp true @ce on success, @cpp false @ce + * otherwise. + * @see @ref features(), @ref convertToFile(const ImageView1D&, Containers::StringView), + * @ref convertToFile(const ImageData1D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const CompressedImageView1D& image, Containers::StringView filename); + /** * @brief Convert a compressed 2D image to a file * @m_since_latest @@ -521,6 +805,32 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToFile(const CompressedImageView2D&, Containers::StringView) instead") bool exportToFile(const CompressedImageView2D& image, const std::string& filename); #endif + /** + * @brief Convert a compressed 3D image to a file + * @m_since_latest + * + * Available only if @ref ImageConverterFeature::ConvertCompressed3DToFile + * or @ref ImageConverterFeature::ConvertCompressed3DToData is + * supported. Returns @cpp true @ce on success, @cpp false @ce + * otherwise. + * @see @ref features(), @ref convertToFile(const ImageView3D&, Containers::StringView), + * @ref convertToFile(const ImageData3D&, Containers::StringView), + * @ref convert(), @ref convertToData() + */ + bool convertToFile(const CompressedImageView3D& image, Containers::StringView filename); + + /** + * @brief Convert a 1D image data to a file + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convertToFile(const ImageView1D&, Containers::StringView) or + * @ref convertToFile(const CompressedImageView1D&, Containers::StringView). + * See documentation of these two functions for details. + * @see @ref ImageData::isCompressed() + */ + bool convertToFile(const ImageData1D& image, Containers::StringView filename); + /** * @brief Convert a 2D image data to a file * @m_since_latest @@ -543,6 +853,18 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract CORRADE_DEPRECATED("use convertToFile(const ImageData2D&, Containers::StringView) instead") bool exportToFile(const ImageData2D& image, const std::string& filename); #endif + /** + * @brief Convert a 3D image data to a file + * @m_since_latest + * + * Based on whether the image is compressed or not, calls either + * @ref convertToFile(const ImageView3D&, Containers::StringView) or + * @ref convertToFile(const CompressedImageView3D&, Containers::StringView). + * See documentation of these two functions for details. + * @see @ref ImageData::isCompressed() + */ + bool convertToFile(const ImageData3D& image, Containers::StringView filename); + private: /** @brief Implementation for @ref features() */ virtual ImageConverterFeatures doFeatures() const = 0; @@ -563,30 +885,88 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ virtual void doSetFlags(ImageConverterFlags flags); + /** + * @brief Implementation for @ref convert(const ImageView1D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const ImageView1D& image); + /** * @brief Implementation for @ref convert(const ImageView2D&) * @m_since_latest */ virtual Containers::Optional doConvert(const ImageView2D& image); + /** + * @brief Implementation for @ref convert(const ImageView3D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const ImageView3D& image); + + /** + * @brief Implementation for @ref convert(const CompressedImageView1D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const CompressedImageView1D& image); + /** * @brief Implementation for @ref convert(const CompressedImageView2D&) * @m_since_latest */ virtual Containers::Optional doConvert(const CompressedImageView2D& image); + /** + * @brief Implementation for @ref convert(const CompressedImageView3D&) + * @m_since_latest + */ + virtual Containers::Optional doConvert(const CompressedImageView3D& image); + + /** + * @brief Implementation for @ref convertToData(const ImageView1D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const ImageView1D& image); + /** * @brief Implementation for @ref convertToData(const ImageView2D&) * @m_since_latest */ virtual Containers::Array doConvertToData(const ImageView2D& image); + /** + * @brief Implementation for @ref convertToData(const ImageView3D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const ImageView3D& image); + + /** + * @brief Implementation for @ref convertToData(const CompressedImageView1D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const CompressedImageView1D& image); + /** * @brief Implementation for @ref convertToData(const CompressedImageView2D&) * @m_since_latest */ virtual Containers::Array doConvertToData(const CompressedImageView2D& image); + /** + * @brief Implementation for @ref convertToData(const CompressedImageView3D&) + * @m_since_latest + */ + virtual Containers::Array doConvertToData(const CompressedImageView3D& image); + + /** + * @brief Implementation for @ref convertToFile(const ImageView1D&, Containers::StringView) + * @m_since_latest + * + * If @ref ImageConverterFeature::Convert1DToData is supported, default + * implementation calls @ref doConvertToData(const ImageView1D&) and + * saves the result to given file. + */ + virtual bool doConvertToFile(const ImageView1D& image, Containers::StringView filename); + /** * @brief Implementation for @ref convertToFile(const ImageView2D&, Containers::StringView) * @m_since_latest @@ -597,6 +977,26 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ virtual bool doConvertToFile(const ImageView2D& image, Containers::StringView filename); + /** + * @brief Implementation for @ref convertToFile(const ImageView3D&, Containers::StringView) + * @m_since_latest + * + * If @ref ImageConverterFeature::Convert3DToData is supported, default + * implementation calls @ref doConvertToData(const ImageView3D&) and + * saves the result to given file. + */ + virtual bool doConvertToFile(const ImageView3D& image, Containers::StringView filename); + + /** + * @brief Implementation for @ref convertToFile(const CompressedImageView1D&, Containers::StringView) + * @m_since_latest + * + * If @ref ImageConverterFeature::ConvertCompressed1DToData is + * supported, default implementation calls @ref doConvertToData(const CompressedImageView1D&) + * and saves the result to given file. + */ + virtual bool doConvertToFile(const CompressedImageView1D& image, Containers::StringView filename); + /** * @brief Implementation for @ref convertToFile(const CompressedImageView2D&, Containers::StringView) * @m_since_latest @@ -607,6 +1007,16 @@ class MAGNUM_TRADE_EXPORT AbstractImageConverter: public PluginManager::Abstract */ virtual bool doConvertToFile(const CompressedImageView2D& image, Containers::StringView filename); + /** + * @brief Implementation for @ref convertToFile(const CompressedImageView3D&, Containers::StringView) + * @m_since_latest + * + * If @ref ImageConverterFeature::ConvertCompressed3DToData is + * supported, default implementation calls @ref doConvertToData(const CompressedImageView3D&) + * and saves the result to given file. + */ + virtual bool doConvertToFile(const CompressedImageView3D& image, Containers::StringView filename); + ImageConverterFlags _flags; }; diff --git a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp index bc1eb317e..ce066f722 100644 --- a/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp +++ b/src/Magnum/Trade/Test/AbstractImageConverterTest.cpp @@ -55,39 +55,89 @@ struct AbstractImageConverterTest: TestSuite::Tester { void thingNotSupported(); + void convert1D(); void convert2D(); + void convert3D(); + void convert1DNotImplemented(); void convert2DNotImplemented(); + void convert3DNotImplemented(); + void convert1DCustomDeleter(); void convert2DCustomDeleter(); + void convert3DCustomDeleter(); + void convertCompressed1D(); void convertCompressed2D(); + void convertCompressed3D(); + void convertCompressed1DNotImplemented(); void convertCompressed2DNotImplemented(); + void convertCompressed3DNotImplemented(); + void convertCompressed1DCustomDeleter(); void convertCompressed2DCustomDeleter(); + void convertCompressed3DCustomDeleter(); + void convertImageData1D(); void convertImageData2D(); + void convertImageData3D(); + void convert1DToData(); void convert2DToData(); + void convert3DToData(); + void convert1DToDataNotImplemented(); void convert2DToDataNotImplemented(); + void convert3DToDataNotImplemented(); + void convert1DToDataCustomDeleter(); void convert2DToDataCustomDeleter(); + void convert3DToDataCustomDeleter(); + void convertCompressed1DToData(); void convertCompressed2DToData(); + void convertCompressed3DToData(); + void convertCompressed1DToDataNotImplemented(); void convertCompressed2DToDataNotImplemented(); + void convertCompressed3DToDataNotImplemented(); + void convertCompressed1DToDataCustomDeleter(); void convertCompressed2DToDataCustomDeleter(); + void convertCompressed3DToDataCustomDeleter(); + void convertImageData1DToData(); void convertImageData2DToData(); + void convertImageData3DToData(); + void convert1DToFile(); void convert2DToFile(); + void convert3DToFile(); + void convert1DToFileThroughData(); void convert2DToFileThroughData(); + void convert3DToFileThroughData(); + void convert1DToFileThroughDataFailed(); void convert2DToFileThroughDataFailed(); + void convert3DToFileThroughDataFailed(); + void convert1DToFileThroughDataNotWritable(); void convert2DToFileThroughDataNotWritable(); + void convert3DToFileThroughDataNotWritable(); + void convert1DToFileNotImplemented(); void convert2DToFileNotImplemented(); + void convert3DToFileNotImplemented(); + void convertCompressed1DToFile(); void convertCompressed2DToFile(); + void convertCompressed3DToFile(); + void convertCompressed1DToFileThroughData(); void convertCompressed2DToFileThroughData(); + void convertCompressed3DToFileThroughData(); + void convertCompressed1DToFileThroughDataFailed(); void convertCompressed2DToFileThroughDataFailed(); + void convertCompressed3DToFileThroughDataFailed(); + void convertCompressed1DToFileThroughDataNotWritable(); void convertCompressed2DToFileThroughDataNotWritable(); + void convertCompressed3DToFileThroughDataNotWritable(); + void convertCompressed1DToFileNotImplemented(); void convertCompressed2DToFileNotImplemented(); + void convertCompressed3DToFileNotImplemented(); + void convertImageData1DToFile(); void convertImageData2DToFile(); + void convertImageData3DToFile(); void debugFeature(); void debugFeatures(); @@ -104,39 +154,89 @@ AbstractImageConverterTest::AbstractImageConverterTest() { &AbstractImageConverterTest::thingNotSupported, + &AbstractImageConverterTest::convert1D, &AbstractImageConverterTest::convert2D, + &AbstractImageConverterTest::convert3D, + &AbstractImageConverterTest::convert1DNotImplemented, &AbstractImageConverterTest::convert2DNotImplemented, + &AbstractImageConverterTest::convert3DNotImplemented, + &AbstractImageConverterTest::convert1DCustomDeleter, &AbstractImageConverterTest::convert2DCustomDeleter, + &AbstractImageConverterTest::convert3DCustomDeleter, + &AbstractImageConverterTest::convertCompressed1D, &AbstractImageConverterTest::convertCompressed2D, + &AbstractImageConverterTest::convertCompressed3D, + &AbstractImageConverterTest::convertCompressed1DNotImplemented, &AbstractImageConverterTest::convertCompressed2DNotImplemented, + &AbstractImageConverterTest::convertCompressed3DNotImplemented, + &AbstractImageConverterTest::convertCompressed1DCustomDeleter, &AbstractImageConverterTest::convertCompressed2DCustomDeleter, + &AbstractImageConverterTest::convertCompressed3DCustomDeleter, + &AbstractImageConverterTest::convertImageData1D, &AbstractImageConverterTest::convertImageData2D, + &AbstractImageConverterTest::convertImageData3D, + &AbstractImageConverterTest::convert1DToData, &AbstractImageConverterTest::convert2DToData, + &AbstractImageConverterTest::convert3DToData, + &AbstractImageConverterTest::convert1DToDataNotImplemented, &AbstractImageConverterTest::convert2DToDataNotImplemented, + &AbstractImageConverterTest::convert3DToDataNotImplemented, + &AbstractImageConverterTest::convert1DToDataCustomDeleter, &AbstractImageConverterTest::convert2DToDataCustomDeleter, + &AbstractImageConverterTest::convert3DToDataCustomDeleter, + &AbstractImageConverterTest::convertCompressed1DToData, &AbstractImageConverterTest::convertCompressed2DToData, + &AbstractImageConverterTest::convertCompressed3DToData, + &AbstractImageConverterTest::convertCompressed1DToDataNotImplemented, &AbstractImageConverterTest::convertCompressed2DToDataNotImplemented, + &AbstractImageConverterTest::convertCompressed3DToDataNotImplemented, + &AbstractImageConverterTest::convertCompressed1DToDataCustomDeleter, &AbstractImageConverterTest::convertCompressed2DToDataCustomDeleter, + &AbstractImageConverterTest::convertCompressed3DToDataCustomDeleter, + &AbstractImageConverterTest::convertImageData1DToData, &AbstractImageConverterTest::convertImageData2DToData, + &AbstractImageConverterTest::convertImageData3DToData, + &AbstractImageConverterTest::convert1DToFile, &AbstractImageConverterTest::convert2DToFile, + &AbstractImageConverterTest::convert3DToFile, + &AbstractImageConverterTest::convert1DToFileThroughData, &AbstractImageConverterTest::convert2DToFileThroughData, + &AbstractImageConverterTest::convert3DToFileThroughData, + &AbstractImageConverterTest::convert1DToFileThroughDataFailed, &AbstractImageConverterTest::convert2DToFileThroughDataFailed, + &AbstractImageConverterTest::convert3DToFileThroughDataFailed, + &AbstractImageConverterTest::convert1DToFileThroughDataNotWritable, &AbstractImageConverterTest::convert2DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convert3DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convert1DToFileNotImplemented, &AbstractImageConverterTest::convert2DToFileNotImplemented, + &AbstractImageConverterTest::convert3DToFileNotImplemented, + &AbstractImageConverterTest::convertCompressed1DToFile, &AbstractImageConverterTest::convertCompressed2DToFile, + &AbstractImageConverterTest::convertCompressed3DToFile, + &AbstractImageConverterTest::convertCompressed1DToFileThroughData, &AbstractImageConverterTest::convertCompressed2DToFileThroughData, + &AbstractImageConverterTest::convertCompressed3DToFileThroughData, + &AbstractImageConverterTest::convertCompressed1DToFileThroughDataFailed, &AbstractImageConverterTest::convertCompressed2DToFileThroughDataFailed, + &AbstractImageConverterTest::convertCompressed3DToFileThroughDataFailed, + &AbstractImageConverterTest::convertCompressed1DToFileThroughDataNotWritable, &AbstractImageConverterTest::convertCompressed2DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convertCompressed3DToFileThroughDataNotWritable, + &AbstractImageConverterTest::convertCompressed1DToFileNotImplemented, &AbstractImageConverterTest::convertCompressed2DToFileNotImplemented, + &AbstractImageConverterTest::convertCompressed3DToFileNotImplemented, + &AbstractImageConverterTest::convertImageData1DToFile, &AbstractImageConverterTest::convertImageData2DToFile, + &AbstractImageConverterTest::convertImageData3DToFile, &AbstractImageConverterTest::debugFeature, &AbstractImageConverterTest::debugFeatures, @@ -215,19 +315,58 @@ void AbstractImageConverterTest::thingNotSupported() { std::ostringstream out; Error redirectError{&out}; + converter.convert(ImageView1D{PixelFormat::R8Unorm, 4, Containers::ArrayView{nullptr, 24}}); converter.convert(ImageView2D{PixelFormat::R8Unorm, {4, 6}, Containers::ArrayView{nullptr, 24}}); + converter.convert(ImageView3D{PixelFormat::R8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 24}}); + converter.convert(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, {nullptr, 64}}); converter.convert(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}); + converter.convert(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, {nullptr, 64}}); + converter.convertToData(ImageView1D{PixelFormat::RGBA8Unorm, 4, Containers::ArrayView{nullptr, 96}}); converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, Containers::ArrayView{nullptr, 96}}); + converter.convertToData(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 96}}); + converter.convertToData(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 64}}); converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + converter.convertToData(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, Containers::ArrayView{nullptr, 64}}); + converter.convertToFile(ImageView1D{PixelFormat::RGBA8Unorm, 4, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); converter.convertToFile(ImageView2D{PixelFormat::RGBA8Unorm, {4, 6}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + converter.convertToFile(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 1}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); converter.convertToFile(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); CORRADE_COMPARE(out.str(), + "Trade::AbstractImageConverter::convert(): 1D image conversion not supported\n" "Trade::AbstractImageConverter::convert(): 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convert(): 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convert(): compressed 1D image conversion not supported\n" "Trade::AbstractImageConverter::convert(): compressed 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convert(): compressed 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): 1D image conversion not supported\n" "Trade::AbstractImageConverter::convertToData(): 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion not supported\n" "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): 1D image conversion not supported\n" "Trade::AbstractImageConverter::convertToFile(): 2D image conversion not supported\n" - "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported\n"); + "Trade::AbstractImageConverter::convertToFile(): 3D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion not supported\n" + "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion not supported\n"); +} + +void AbstractImageConverterTest::convert1D() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; } + Containers::Optional doConvert(const ImageView1D& image) override { + return ImageData1D{PixelFormat::RGBA8Unorm, image.size(), Containers::Array{16}}; + } + } converter; + + Containers::Optional actual = converter.convert(ImageView1D{PixelFormat::R8Unorm, 4, Containers::ArrayView{nullptr, 24}}); + CORRADE_VERIFY(actual); + CORRADE_VERIFY(!actual->isCompressed()); + CORRADE_COMPARE(actual->data().size(), 16); + CORRADE_COMPARE(actual->size(), 4); } void AbstractImageConverterTest::convert2D() { @@ -245,6 +384,36 @@ void AbstractImageConverterTest::convert2D() { CORRADE_COMPARE(actual->size(), (Vector2i{4, 6})); } +void AbstractImageConverterTest::convert3D() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3D; } + Containers::Optional doConvert(const ImageView3D& image) override { + return ImageData3D{PixelFormat::RGBA8Unorm, image.size(), Containers::Array{96}}; + } + } converter; + + Containers::Optional actual = converter.convert(ImageView3D{PixelFormat::R8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 24}}); + CORRADE_VERIFY(actual); + CORRADE_VERIFY(!actual->isCompressed()); + CORRADE_COMPARE(actual->data().size(), 96); + CORRADE_COMPARE(actual->size(), (Vector3i{4, 6, 1})); +} + +void AbstractImageConverterTest::convert1DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(ImageView1D{PixelFormat::R8Unorm, 4, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convert2DNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -260,6 +429,39 @@ void AbstractImageConverterTest::convert2DNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): 2D image conversion advertised but not implemented\n"); } +void AbstractImageConverterTest::convert3DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3D; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(ImageView3D{PixelFormat::R8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convert1DCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D; } + Containers::Optional doConvert(const ImageView1D&) override { + return ImageData1D{PixelFormat::RGBA8Unorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(ImageView1D{PixelFormat::R8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); +} + void AbstractImageConverterTest::convert2DCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -278,6 +480,39 @@ void AbstractImageConverterTest::convert2DCustomDeleter() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); } +void AbstractImageConverterTest::convert3DCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3D; } + Containers::Optional doConvert(const ImageView3D&) override { + return ImageData3D{PixelFormat::RGBA8Unorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(ImageView3D{PixelFormat::R8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); +} + +void AbstractImageConverterTest::convertCompressed1D() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1D; } + Containers::Optional doConvert(const CompressedImageView1D& image) override { + return ImageData1D{image.format(), image.size(), Containers::Array{64}}; + } + } converter; + + Containers::Optional actual = converter.convert(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 128}}); + CORRADE_VERIFY(actual); + CORRADE_VERIFY(actual->isCompressed()); + CORRADE_COMPARE(actual->data().size(), 64); + CORRADE_COMPARE(actual->size(), 16); +} + void AbstractImageConverterTest::convertCompressed2D() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2D; } @@ -293,6 +528,36 @@ void AbstractImageConverterTest::convertCompressed2D() { CORRADE_COMPARE(actual->size(), (Vector2i{16, 8})); } +void AbstractImageConverterTest::convertCompressed3D() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3D; } + Containers::Optional doConvert(const CompressedImageView3D& image) override { + return ImageData3D{image.format(), image.size(), Containers::Array{64}}; + } + } converter; + + Containers::Optional actual = converter.convert(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, Containers::ArrayView{nullptr, 128}}); + CORRADE_VERIFY(actual); + CORRADE_VERIFY(actual->isCompressed()); + CORRADE_COMPARE(actual->data().size(), 64); + CORRADE_COMPARE(actual->size(), (Vector3i{16, 8, 1})); +} + +void AbstractImageConverterTest::convertCompressed1DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1D; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): compressed 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convertCompressed2DNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -308,6 +573,39 @@ void AbstractImageConverterTest::convertCompressed2DNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): compressed 2D image conversion advertised but not implemented\n"); } +void AbstractImageConverterTest::convertCompressed3DNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3D; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, Containers::ArrayView{nullptr, 128}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): compressed 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed1DCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1D; } + Containers::Optional doConvert(const CompressedImageView1D&) override { + return ImageData1D{CompressedPixelFormat::Bc1RGBAUnorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); +} + void AbstractImageConverterTest::convertCompressed2DCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -326,6 +624,56 @@ void AbstractImageConverterTest::convertCompressed2DCustomDeleter() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); } +void AbstractImageConverterTest::convertCompressed3DCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3D; } + Containers::Optional doConvert(const CompressedImageView3D&) override { + return ImageData3D{CompressedPixelFormat::Bc1RGBAUnorm, {}, Containers::Array{nullptr, 0, [](char*, std::size_t) {}}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convert(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convert(): implementation is not allowed to use a custom Array deleter\n"); +} + +void AbstractImageConverterTest::convertImageData1D() { + struct: Trade::AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1D|ImageConverterFeature::ConvertCompressed1D; } + + Containers::Optional doConvert(const ImageView1D&) override { + return ImageData1D{PixelFormat::R8Unorm, {}, Containers::array({'B'})}; + }; + + Containers::Optional doConvert(const CompressedImageView1D&) override { + return ImageData1D{PixelFormat::R8Unorm, {}, Containers::array({'C'})}; + }; + } converter; + + { + /* Should get "B" when converting uncompressed */ + ImageData1D image{PixelFormat::RGBA8Unorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + } { + /* Should get "C" when converting compressed */ + ImageData1D image{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); + } +} + void AbstractImageConverterTest::convertImageData2D() { struct: Trade::AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2D|ImageConverterFeature::ConvertCompressed2D; } @@ -358,6 +706,50 @@ void AbstractImageConverterTest::convertImageData2D() { } } +void AbstractImageConverterTest::convertImageData3D() { + struct: Trade::AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3D|ImageConverterFeature::ConvertCompressed3D; } + + Containers::Optional doConvert(const ImageView3D&) override { + return ImageData3D{PixelFormat::R8Unorm, {}, Containers::array({'B'})}; + }; + + Containers::Optional doConvert(const CompressedImageView3D&) override { + return ImageData3D{PixelFormat::R8Unorm, {}, Containers::array({'C'})}; + }; + } converter; + + { + /* Should get "B" when converting uncompressed */ + ImageData3D image{PixelFormat::RGBA8Unorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + } { + /* Should get "C" when converting compressed */ + ImageData3D image{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}; + Containers::Optional out = converter.convert(image); + CORRADE_VERIFY(out); + CORRADE_COMPARE_AS(out->data(), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); + } +} + +void AbstractImageConverterTest::convert1DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + Containers::Array doConvertToData(const ImageView1D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; + + Containers::Array actual = converter.convertToData(ImageView1D{PixelFormat::RGBA8Unorm, 4, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(actual.size(), 4); +} + void AbstractImageConverterTest::convert2DToData() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } @@ -370,6 +762,33 @@ void AbstractImageConverterTest::convert2DToData() { CORRADE_COMPARE(actual.size(), 24); } +void AbstractImageConverterTest::convert3DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + Containers::Array doConvertToData(const ImageView3D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; + + Containers::Array actual = converter.convertToData(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 2}, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(actual.size(), 48); +} + +void AbstractImageConverterTest::convert1DToDataNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(ImageView1D{PixelFormat::RGBA8Unorm, 4, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convert2DToDataNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -385,85 +804,264 @@ void AbstractImageConverterTest::convert2DToDataNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): 2D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::convert2DToDataCustomDeleter() { +void AbstractImageConverterTest::convert3DToDataNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } - Containers::Array doConvertToData(const ImageView2D&) override { - return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; - } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); + converter.convertToData(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 1}, Containers::ArrayView{nullptr, 96}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): 3D image conversion advertised but not implemented\n"); } -void AbstractImageConverterTest::convertCompressed2DToData() { +void AbstractImageConverterTest::convert1DToDataCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } - Containers::Array doConvertToData(const CompressedImageView2D& image) override { - return Containers::Array{nullptr, std::size_t(image.size().product())}; + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + Containers::Array doConvertToData(const ImageView1D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; } } converter; - Containers::Array actual = converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); - CORRADE_COMPARE(actual.size(), 128); + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(ImageView1D{PixelFormat::RGBA8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); } -void AbstractImageConverterTest::convertCompressed2DToDataNotImplemented() { +void AbstractImageConverterTest::convert2DToDataCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } + Containers::Array doConvertToData(const ImageView2D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } } converter; std::ostringstream out; Error redirectError{&out}; - converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); - CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion advertised but not implemented\n"); + converter.convertToData(ImageView2D{PixelFormat::RGBA8Unorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); } -void AbstractImageConverterTest::convertCompressed2DToDataCustomDeleter() { +void AbstractImageConverterTest::convert3DToDataCustomDeleter() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif struct: AbstractImageConverter { - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } - Containers::Array doConvertToData(const CompressedImageView2D&) override { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + Containers::Array doConvertToData(const ImageView3D&) override { return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; } } converter; std::ostringstream out; Error redirectError{&out}; - converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + converter.convertToData(ImageView3D{PixelFormat::RGBA8Unorm, {}}); CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); } -/* Used by convertImageDataToData() and convertImageDataToFile() */ -class ImageData2DConverter: public Trade::AbstractImageConverter { - private: - ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData|ImageConverterFeature::ConvertCompressed2DToData; } - - Containers::Array doConvertToData(const ImageView2D&) override { - return Containers::array({'B'}); - }; - - Containers::Array doConvertToData(const CompressedImageView2D&) override { - return Containers::array({'C'}); - }; -}; +void AbstractImageConverterTest::convertCompressed1DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + Containers::Array doConvertToData(const CompressedImageView1D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; -void AbstractImageConverterTest::convertImageData2DToData() { - ImageData2DConverter converter; + Containers::Array actual = converter.convertToData(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(actual.size(), 16); +} + +void AbstractImageConverterTest::convertCompressed2DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + Containers::Array doConvertToData(const CompressedImageView2D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; + + Containers::Array actual = converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(actual.size(), 128); +} + +void AbstractImageConverterTest::convertCompressed3DToData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + Containers::Array doConvertToData(const CompressedImageView3D& image) override { + return Containers::Array{nullptr, std::size_t(image.size().product())}; + } + } converter; + + Containers::Array actual = converter.convertToData(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 2}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(actual.size(), 256); +} + +void AbstractImageConverterTest::convertCompressed1DToDataNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 1D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed2DToDataNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 2D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed3DToDataNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, Containers::ArrayView{nullptr, 64}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): compressed 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed1DToDataCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + Containers::Array doConvertToData(const CompressedImageView1D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); +} + +void AbstractImageConverterTest::convertCompressed2DToDataCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } + Containers::Array doConvertToData(const CompressedImageView2D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView2D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); +} + +void AbstractImageConverterTest::convertCompressed3DToDataCustomDeleter() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + Containers::Array doConvertToData(const CompressedImageView3D&) override { + return Containers::Array{nullptr, 0, [](char*, std::size_t) {}}; + } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToData(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {}}); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToData(): implementation is not allowed to use a custom Array deleter\n"); +} + +/* Used by convertImageDataToData() and convertImageDataToFile() */ +class ImageData1DConverter: public Trade::AbstractImageConverter { + private: + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData|ImageConverterFeature::ConvertCompressed1DToData; } + + Containers::Array doConvertToData(const ImageView1D&) override { + return Containers::array({'B'}); + }; + + Containers::Array doConvertToData(const CompressedImageView1D&) override { + return Containers::array({'C'}); + }; +}; +class ImageData2DConverter: public Trade::AbstractImageConverter { + private: + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData|ImageConverterFeature::ConvertCompressed2DToData; } + + Containers::Array doConvertToData(const ImageView2D&) override { + return Containers::array({'B'}); + }; + + Containers::Array doConvertToData(const CompressedImageView2D&) override { + return Containers::array({'C'}); + }; +}; +class ImageData3DConverter: public Trade::AbstractImageConverter { + private: + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData|ImageConverterFeature::ConvertCompressed3DToData; } + + Containers::Array doConvertToData(const ImageView3D&) override { + return Containers::array({'B'}); + }; + + Containers::Array doConvertToData(const CompressedImageView3D&) override { + return Containers::array({'C'}); + }; +}; + +void AbstractImageConverterTest::convertImageData1DToData() { + ImageData1DConverter converter; + + /* Should get "B" when converting uncompressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData1D{PixelFormat::RGBA8Unorm, {}, nullptr}), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + + /* Should get "C" when converting compressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData1D{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); +} + +void AbstractImageConverterTest::convertImageData2DToData() { + ImageData2DConverter converter; /* Should get "B" when converting uncompressed */ CORRADE_COMPARE_AS(converter.convertToData(ImageData2D{PixelFormat::RGBA8Unorm, {}, nullptr}), @@ -476,6 +1074,40 @@ void AbstractImageConverterTest::convertImageData2DToData() { TestSuite::Compare::Container); } +void AbstractImageConverterTest::convertImageData3DToData() { + ImageData3DConverter converter; + + /* Should get "B" when converting uncompressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData3D{PixelFormat::RGBA8Unorm, {}, nullptr}), + Containers::arrayView({'B'}), + TestSuite::Compare::Container); + + /* Should get "C" when converting compressed */ + CORRADE_COMPARE_AS(converter.convertToData(ImageData3D{CompressedPixelFormat::Bc1RGBUnorm, {}, nullptr}), + Containers::arrayView({'C'}), + TestSuite::Compare::Container); +} + +void AbstractImageConverterTest::convert1DToFile() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToFile; } + bool doConvertToFile(const ImageView1D& image, Containers::StringView filename) override { + return Utility::Directory::write(filename, Containers::arrayView( + {char(image.size()[0])})); + } + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + CORRADE_VERIFY(converter.convertToFile(ImageView1D{PixelFormat::RGBA8Unorm, 0xf0, {nullptr, 0xf0*4}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xf0", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convert2DToFile() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToFile; } @@ -496,6 +1128,47 @@ void AbstractImageConverterTest::convert2DToFile() { "\xf0\x0d", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convert3DToFile() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToFile; } + bool doConvertToFile(const ImageView3D& image, Containers::StringView filename) override { + return Utility::Directory::write(filename, Containers::arrayView( + {char(image.size().x()), char(image.size().y()), char(image.size().z())})); + } + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + CORRADE_VERIFY(converter.convertToFile(ImageView3D{PixelFormat::RGBA8Unorm, {0xf0, 0x0d, 0x1e}, {nullptr, 0xf0*0x0d*0x1e*4}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xf0\x0d\x1e", TestSuite::Compare::FileToString); +} + +void AbstractImageConverterTest::convert1DToFileThroughData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + + Containers::Array doConvertToData(const ImageView1D& image) override { + return Containers::array({char(image.size()[0])}); + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(ImageView1D(PixelFormat::RGBA8Unorm, 0xfe, {nullptr, 0xfe*4}), filename)); + CORRADE_COMPARE_AS(filename, + "\xfe", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convert2DToFileThroughData() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } @@ -517,6 +1190,51 @@ void AbstractImageConverterTest::convert2DToFileThroughData() { "\xfe\xed", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convert3DToFileThroughData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + + Containers::Array doConvertToData(const ImageView3D& image) override { + return Containers::array({char(image.size().x()), char(image.size().y()), char(image.size().z())}); + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(ImageView3D(PixelFormat::RGBA8Unorm, {0xfe, 0xed, 0xe9}, {nullptr, 0xfe*0xed*0xe9*4}), filename)); + CORRADE_COMPARE_AS(filename, + "\xfe\xed\xe9", TestSuite::Compare::FileToString); +} + +void AbstractImageConverterTest::convert1DToFileThroughDataFailed() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + + Containers::Array doConvertToData(const ImageView1D&) override { + return {}; + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(ImageView1D(PixelFormat::RGBA8Unorm, 0xfe, {nullptr, 0xfe*4}), filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} + void AbstractImageConverterTest::convert2DToFileThroughDataFailed() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } @@ -541,6 +1259,47 @@ void AbstractImageConverterTest::convert2DToFileThroughDataFailed() { CORRADE_COMPARE(out.str(), ""); } +void AbstractImageConverterTest::convert3DToFileThroughDataFailed() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + + Containers::Array doConvertToData(const ImageView3D&) override { + return {}; + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(ImageView3D(PixelFormat::RGBA8Unorm, {0xfe, 0xed, 0xe9}, {nullptr, 0xfe*0xed*0xe9*4}), filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} + +void AbstractImageConverterTest::convert1DToFileThroughDataNotWritable() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToData; } + + Containers::Array doConvertToData(const ImageView1D& image) override { + return Containers::array({char(image.size()[0])}); + }; + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(ImageView1D{PixelFormat::RGBA8Unorm, 0xfe, {nullptr, 0xfe*4}}, "/some/path/that/does/not/exist")); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + void AbstractImageConverterTest::convert2DToFileThroughDataNotWritable() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert2DToData; } @@ -558,6 +1317,38 @@ void AbstractImageConverterTest::convert2DToFileThroughDataNotWritable() { "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); } +void AbstractImageConverterTest::convert3DToFileThroughDataNotWritable() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToData; } + + Containers::Array doConvertToData(const ImageView3D& image) override { + return Containers::array({char(image.size().x()), char(image.size().y()), char(image.size().z())}); + }; + } converter; + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(ImageView3D{PixelFormat::RGBA8Unorm, {0xfe, 0xed, 0xe9}, {nullptr, 0xfe*0xed*0xe9*4}}, "/some/path/that/does/not/exist")); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + +void AbstractImageConverterTest::convert1DToFileNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert1DToFile; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(ImageView1D{PixelFormat::RGBA8Unorm, 4, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convert2DToFileNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -573,6 +1364,41 @@ void AbstractImageConverterTest::convert2DToFileNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): 2D image conversion advertised but not implemented\n"); } +void AbstractImageConverterTest::convert3DToFileNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::Convert3DToFile; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(ImageView3D{PixelFormat::RGBA8Unorm, {4, 6, 1}, {nullptr, 96}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertCompressed1DToFile() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToFile; } + bool doConvertToFile(const CompressedImageView1D& image, Containers::StringView filename) override { + return Utility::Directory::write(filename, Containers::arrayView( + {char(image.size()[0])})); + } + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + CORRADE_VERIFY(converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 0xd0, {nullptr, 64}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xd0", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convertCompressed2DToFile() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToFile; } @@ -593,6 +1419,47 @@ void AbstractImageConverterTest::convertCompressed2DToFile() { "\xd0\x0d", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convertCompressed3DToFile() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToFile; } + bool doConvertToFile(const CompressedImageView3D& image, Containers::StringView filename) override { + return Utility::Directory::write(filename, Containers::arrayView( + {char(image.size().x()), char(image.size().y()), char(image.size().z())})); + } + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + CORRADE_VERIFY(converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {0xd0, 0x0d, 0x1e}, {nullptr, 64}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xd0\x0d\x1e", TestSuite::Compare::FileToString); +} + +void AbstractImageConverterTest::convertCompressed1DToFileThroughData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + + Containers::Array doConvertToData(const CompressedImageView1D& image) override { + return Containers::array({char(image.size()[0])}); + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 0xb0, {nullptr, 64}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xb0", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convertCompressed2DToFileThroughData() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } @@ -614,6 +1481,51 @@ void AbstractImageConverterTest::convertCompressed2DToFileThroughData() { "\xb0\xd9", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convertCompressed3DToFileThroughData() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + + Containers::Array doConvertToData(const CompressedImageView3D& image) override { + return Containers::array({char(image.size().x()), char(image.size().y()), char(image.size().z())}); + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* doConvertToFile() should call doConvertToData() */ + CORRADE_VERIFY(converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {0xb0, 0xd1, 0xe5}, {nullptr, 64}}, filename)); + CORRADE_COMPARE_AS(filename, + "\xb0\xd1\xe5", TestSuite::Compare::FileToString); +} + +void AbstractImageConverterTest::convertCompressed1DToFileThroughDataFailed() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + + Containers::Array doConvertToData(const CompressedImageView1D&) override { + return {}; + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 0xb0, {nullptr, 64}}, filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} + void AbstractImageConverterTest::convertCompressed2DToFileThroughDataFailed() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } @@ -638,6 +1550,47 @@ void AbstractImageConverterTest::convertCompressed2DToFileThroughDataFailed() { CORRADE_COMPARE(out.str(), ""); } +void AbstractImageConverterTest::convertCompressed3DToFileThroughDataFailed() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + + Containers::Array doConvertToData(const CompressedImageView3D&) override { + return {}; + }; + } converter; + + const std::string filename = Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"); + + /* Remove previous file, if any */ + Utility::Directory::rm(filename); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + + /* Function should fail, no file should get written and no error output + should be printed (the base implementation assumes the plugin does it) */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {0xb0, 0xd1, 0xe5}, {nullptr, 64}}, filename)); + CORRADE_VERIFY(!Utility::Directory::exists(filename)); + CORRADE_COMPARE(out.str(), ""); +} + +void AbstractImageConverterTest::convertCompressed1DToFileThroughDataNotWritable() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToData; } + + Containers::Array doConvertToData(const CompressedImageView1D& image) override { + return Containers::array({char(image.size()[0])}); + }; + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, {nullptr, 64}}, "/some/path/that/does/not/exist"); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + void AbstractImageConverterTest::convertCompressed2DToFileThroughDataNotWritable() { struct: AbstractImageConverter { ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed2DToData; } @@ -655,6 +1608,38 @@ void AbstractImageConverterTest::convertCompressed2DToFileThroughDataNotWritable "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); } +void AbstractImageConverterTest::convertCompressed3DToFileThroughDataNotWritable() { + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToData; } + + Containers::Array doConvertToData(const CompressedImageView3D& image) override { + return Containers::array({char(image.size().x()), char(image.size().y()), char(image.size().z())}); + }; + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, {nullptr, 64}}, "/some/path/that/does/not/exist"); + CORRADE_COMPARE(out.str(), + "Utility::Directory::write(): can't open /some/path/that/does/not/exist\n" + "Trade::AbstractImageConverter::convertToFile(): cannot write to file /some/path/that/does/not/exist\n"); +} + +void AbstractImageConverterTest::convertCompressed1DToFileNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed1DToFile; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(CompressedImageView1D{CompressedPixelFormat::Bc1RGBAUnorm, 16, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): compressed 1D image conversion advertised but not implemented\n"); +} + void AbstractImageConverterTest::convertCompressed2DToFileNotImplemented() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); @@ -670,6 +1655,35 @@ void AbstractImageConverterTest::convertCompressed2DToFileNotImplemented() { CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): compressed 2D image conversion advertised but not implemented\n"); } +void AbstractImageConverterTest::convertCompressed3DToFileNotImplemented() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + struct: AbstractImageConverter { + ImageConverterFeatures doFeatures() const override { return ImageConverterFeature::ConvertCompressed3DToFile; } + } converter; + + std::ostringstream out; + Error redirectError{&out}; + converter.convertToFile(CompressedImageView3D{CompressedPixelFormat::Bc1RGBAUnorm, {16, 8, 1}, {nullptr, 64}}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out")); + CORRADE_COMPARE(out.str(), "Trade::AbstractImageConverter::convertToFile(): compressed 3D image conversion advertised but not implemented\n"); +} + +void AbstractImageConverterTest::convertImageData1DToFile() { + ImageData1DConverter converter; + + /* Should get "B" when converting uncompressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData1D{PixelFormat::RGBA16F, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "B", TestSuite::Compare::FileToString); + + /* Should get "C" when converting compressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData1D{CompressedPixelFormat::Bc2RGBAUnorm, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "C", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::convertImageData2DToFile() { ImageData2DConverter converter; @@ -684,6 +1698,20 @@ void AbstractImageConverterTest::convertImageData2DToFile() { "C", TestSuite::Compare::FileToString); } +void AbstractImageConverterTest::convertImageData3DToFile() { + ImageData3DConverter converter; + + /* Should get "B" when converting uncompressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData3D{PixelFormat::RGBA16F, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "B", TestSuite::Compare::FileToString); + + /* Should get "C" when converting compressed */ + CORRADE_VERIFY(converter.convertToFile(ImageData3D{CompressedPixelFormat::Bc2RGBAUnorm, {}, nullptr}, Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"))); + CORRADE_COMPARE_AS(Utility::Directory::join(TRADE_TEST_OUTPUT_DIR, "image.out"), + "C", TestSuite::Compare::FileToString); +} + void AbstractImageConverterTest::debugFeature() { std::ostringstream out; From 60843307c0df8b7e0023a5a83185f19db1ae497c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 12 Apr 2021 12:18:16 +0200 Subject: [PATCH 128/161] Trade: doc++ --- src/Magnum/Trade/AbstractImageConverter.h | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Magnum/Trade/AbstractImageConverter.h b/src/Magnum/Trade/AbstractImageConverter.h index 02a147d6a..e44adc466 100644 --- a/src/Magnum/Trade/AbstractImageConverter.h +++ b/src/Magnum/Trade/AbstractImageConverter.h @@ -327,18 +327,23 @@ You don't need to do most of the redundant sanity checks, these things are checked by the implementation: - The function @ref doConvert(const ImageView2D&) is called only if - @ref ImageConverterFeature::Convert2D is supported. + @ref ImageConverterFeature::Convert2D is supported and equivalently for the + 1D and 3D case. - The function @ref doConvert(const CompressedImageView2D&) is called only if - @ref ImageConverterFeature::ConvertCompressed2D is supported. + @ref ImageConverterFeature::ConvertCompressed2D is supported and + equivalently for the 1D and 3D case. - The function @ref doConvertToData(const ImageView2D&) is called only if - @ref ImageConverterFeature::Convert2DToData is supported. + @ref ImageConverterFeature::Convert2DToData is supported and equivalently + for the 1D and 3D case. - The function @ref doConvertToData(const CompressedImageView2D&) is called - only if @ref ImageConverterFeature::ConvertCompressed2DToData is supported. + only if @ref ImageConverterFeature::ConvertCompressed2DToData is supported + and equivalently for the 1D and 3D case. - The function @ref doConvertToFile(const ImageView2D&, Containers::StringView) - is called only if @ref ImageConverterFeature::Convert2DToFile is supported. + is called only if @ref ImageConverterFeature::Convert2DToFile is supported + and equivalently for the 1D and 3D case. - The function @ref doConvertToFile(const CompressedImageView2D&, Containers::StringView) is called only if @ref ImageConverterFeature::ConvertCompressed2DToFile is - supported. + supported and equivalently for the 1D and 3D case. @m_class{m-block m-warning} From 595421da16080ee7019bd0651359f145b2c65077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 12 Apr 2021 11:12:34 +0200 Subject: [PATCH 129/161] GL: rename & reorganize cubemap internals and test cases for clarity. The 3D subimage setters/queries will get enabled on all platforms now, and naming them "full" just doesn't make sense. --- src/Magnum/GL/CubeMapTexture.cpp | 12 +- src/Magnum/GL/Implementation/TextureState.cpp | 13 +- src/Magnum/GL/Implementation/TextureState.h | 4 +- src/Magnum/GL/Test/CubeMapTextureGLTest.cpp | 214 +++++++++--------- 4 files changed, 121 insertions(+), 122 deletions(-) diff --git a/src/Magnum/GL/CubeMapTexture.cpp b/src/Magnum/GL/CubeMapTexture.cpp index f92e634a5..9651f4ba0 100644 --- a/src/Magnum/GL/CubeMapTexture.cpp +++ b/src/Magnum/GL/CubeMapTexture.cpp @@ -76,7 +76,7 @@ void CubeMapTexture::image(const Int level, Image3D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Context::current().state().renderer.applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture.getFullCubeImageImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data, image.storage()); + (this->*Context::current().state().texture.getCubeImage3DImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), data.size(), data, image.storage()); image = Image3D{image.storage(), image.format(), image.formatExtra(), image.pixelSize(), size, std::move(data)}; } @@ -94,7 +94,7 @@ void CubeMapTexture::image(const Int level, const MutableImageView3D& image) { Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Context::current().state().renderer.applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture.getFullCubeImageImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data(), image.storage()); + (this->*Context::current().state().texture.getCubeImage3DImplementation)(level, size, pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data().size(), image.data(), image.storage()); } void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUsage usage) { @@ -111,7 +111,7 @@ void CubeMapTexture::image(const Int level, BufferImage3D& image, const BufferUs image.buffer().bindInternal(Buffer::TargetHint::PixelPack); Context::current().state().renderer.applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture.getFullCubeImageImplementation)(level, size, image.format(), image.type(), dataSize, nullptr, image.storage()); + (this->*Context::current().state().texture.getCubeImage3DImplementation)(level, size, image.format(), image.type(), dataSize, nullptr, image.storage()); } BufferImage3D CubeMapTexture::image(const Int level, BufferImage3D&& image, const BufferUsage usage) { @@ -147,7 +147,7 @@ void CubeMapTexture::compressedImage(const Int level, CompressedImage3D& image) Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Context::current().state().renderer.applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture.getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, data); + (this->*Context::current().state().texture.getCompressedCubeImage3DImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, data); image = CompressedImage3D{image.storage(), CompressedPixelFormat(format), size, std::move(data)}; } @@ -190,7 +190,7 @@ void CubeMapTexture::compressedImage(const Int level, const MutableCompressedIma Buffer::unbindInternal(Buffer::TargetHint::PixelPack); Context::current().state().renderer.applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture.getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, image.data()); + (this->*Context::current().state().texture.getCompressedCubeImage3DImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, image.data()); } void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& image, const BufferUsage usage) { @@ -222,7 +222,7 @@ void CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D& i image.buffer().bindInternal(Buffer::TargetHint::PixelPack); Context::current().state().renderer.applyPixelStoragePack(image.storage()); - (this->*Context::current().state().texture.getFullCompressedCubeImageImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, nullptr); + (this->*Context::current().state().texture.getCompressedCubeImage3DImplementation)(level, size.xy(), dataOffsetSize.first, dataOffsetSize.second, nullptr); } CompressedBufferImage3D CubeMapTexture::compressedImage(const Int level, CompressedBufferImage3D&& image, const BufferUsage usage) { diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index 4a61fa103..374ba2ff7 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -326,14 +326,14 @@ TextureState::TextureState(Context& context, getCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDefault; } - /* Full compressed cubemap image query implementation (extensions added + /* 3D compressed cubemap image query implementation (extensions added above) */ if((context.detectedDriver() & Context::DetectedDriver::NVidia) && context.isExtensionSupported() && !context.isDriverWorkaroundDisabled("nv-cubemap-broken-full-compressed-image-query"_s)) - getFullCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSASingleSliceWorkaround; + getCompressedCubeImage3DImplementation = &CubeMapTexture::getCompressedImageImplementationDSASingleSliceWorkaround; else - getFullCompressedCubeImageImplementation = &CubeMapTexture::getCompressedImageImplementationDSA; + getCompressedCubeImage3DImplementation = &CubeMapTexture::getCompressedImageImplementationDSA; #ifdef CORRADE_TARGET_WINDOWS /** @todo those *might* be happening with the proprietary AMD driver on @@ -341,15 +341,14 @@ TextureState::TextureState(Context& context, if((context.detectedDriver() & Context::DetectedDriver::Amd) && context.isExtensionSupported() && !context.isDriverWorkaroundDisabled("amd-windows-cubemap-image3d-slice-by-slice"_s)) - getFullCubeImageImplementation = &CubeMapTexture::getImageImplementationDSAAmdSliceBySlice; + getCubeImage3DImplementation = &CubeMapTexture::getImageImplementationDSAAmdSliceBySlice; else if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && context.isExtensionSupported() && !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps"_s)) - getFullCubeImageImplementation = &CubeMapTexture::getImageImplementationSliceBySlice; + getCubeImage3DImplementation = &CubeMapTexture::getImageImplementationSliceBySlice; else #endif - { - getFullCubeImageImplementation = &CubeMapTexture::getImageImplementationDSA; + getCubeImage3DImplementation = &CubeMapTexture::getImageImplementationSliceBySlice; } #endif diff --git a/src/Magnum/GL/Implementation/TextureState.h b/src/Magnum/GL/Implementation/TextureState.h index fcb22b91e..a0477a93f 100644 --- a/src/Magnum/GL/Implementation/TextureState.h +++ b/src/Magnum/GL/Implementation/TextureState.h @@ -122,8 +122,8 @@ struct TextureState { #ifndef MAGNUM_TARGET_GLES GLint(CubeMapTexture::*getCubeLevelCompressedImageSizeImplementation)(GLint); void(CubeMapTexture::*getCubeImageImplementation)(CubeMapCoordinate, GLint, const Vector2i&, PixelFormat, PixelType, std::size_t, GLvoid*); - void(CubeMapTexture::*getFullCubeImageImplementation)(GLint, const Vector3i&, PixelFormat, PixelType, std::size_t, GLvoid*, const PixelStorage&); - void(CubeMapTexture::*getFullCompressedCubeImageImplementation)(GLint, const Vector2i&, std::size_t, std::size_t, GLvoid*); + void(CubeMapTexture::*getCubeImage3DImplementation)(GLint, const Vector3i&, PixelFormat, PixelType, std::size_t, GLvoid*, const PixelStorage&); + void(CubeMapTexture::*getCompressedCubeImage3DImplementation)(GLint, const Vector2i&, std::size_t, std::size_t, GLvoid*); void(CubeMapTexture::*getCompressedCubeImageImplementation)(CubeMapCoordinate, GLint, const Vector2i&, std::size_t, GLvoid*); void(CubeMapTexture::*cubeSubImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&); #endif diff --git a/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp b/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp index 4d46d284b..41f78f076 100644 --- a/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp @@ -129,19 +129,19 @@ struct CubeMapTextureGLTest: OpenGLTester { #endif #ifndef MAGNUM_TARGET_GLES - void fullImageQuery(); - void fullImageQueryView(); - void fullImageQueryViewNullptr(); - void fullImageQueryViewBadSize(); - void fullImageQueryBuffer(); + void image3D(); + void image3DBuffer(); + void image3DQueryView(); + void image3DQueryViewNullptr(); + void image3DQueryViewBadSize(); - void compressedFullImageQuery(); - void compressedFullImageQueryView(); - void compressedFullImageQueryViewNullptr(); - void compressedFullImageQueryViewBadSize(); - void compressedFullImageQueryViewBadDataSize(); - void compressedFullImageQueryViewBadFormat(); - void compressedFullImageQueryBuffer(); + void compressedImage3D(); + void compressedImage3DBuffer(); + void compressedImage3DQueryView(); + void compressedImage3DQueryViewNullptr(); + void compressedImage3DQueryViewBadSize(); + void compressedImage3DQueryViewBadDataSize(); + void compressedImage3DQueryViewBadFormat(); #endif void generateMipmap(); @@ -350,13 +350,13 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { #ifndef MAGNUM_TARGET_GLES addInstancedTests({ - &CubeMapTextureGLTest::fullImageQuery, - &CubeMapTextureGLTest::fullImageQueryView, - &CubeMapTextureGLTest::fullImageQueryBuffer}, + &CubeMapTextureGLTest::image3D, + &CubeMapTextureGLTest::image3DBuffer, + &CubeMapTextureGLTest::image3DQueryView}, Containers::arraySize(FullPixelStorageData)); - addTests({&CubeMapTextureGLTest::fullImageQueryViewNullptr, - &CubeMapTextureGLTest::fullImageQueryViewBadSize}); + addTests({&CubeMapTextureGLTest::image3DQueryViewNullptr, + &CubeMapTextureGLTest::image3DQueryViewBadSize}); #endif addInstancedTests({ @@ -391,15 +391,15 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { &CubeMapTextureGLTest::compressedImageQueryViewBadFormat}); addInstancedTests({ - &CubeMapTextureGLTest::compressedFullImageQuery, - &CubeMapTextureGLTest::compressedFullImageQueryView, - &CubeMapTextureGLTest::compressedFullImageQueryBuffer}, + &CubeMapTextureGLTest::compressedImage3D, + &CubeMapTextureGLTest::compressedImage3DBuffer, + &CubeMapTextureGLTest::compressedImage3DQueryView}, Containers::arraySize(CompressedFullPixelStorageData)); - addTests({&CubeMapTextureGLTest::compressedFullImageQueryViewNullptr, - &CubeMapTextureGLTest::compressedFullImageQueryViewBadSize, - &CubeMapTextureGLTest::compressedFullImageQueryViewBadDataSize, - &CubeMapTextureGLTest::compressedFullImageQueryViewBadFormat}); + addTests({&CubeMapTextureGLTest::compressedImage3DQueryViewNullptr, + &CubeMapTextureGLTest::compressedImage3DQueryViewBadSize, + &CubeMapTextureGLTest::compressedImage3DQueryViewBadDataSize, + &CubeMapTextureGLTest::compressedImage3DQueryViewBadFormat}); #endif addInstancedTests({ @@ -1736,7 +1736,7 @@ void CubeMapTextureGLTest::compressedSubImageQueryBuffer() { #endif #ifndef MAGNUM_TARGET_GLES -void CubeMapTextureGLTest::fullImageQuery() { +void CubeMapTextureGLTest::image3D() { setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) @@ -1765,7 +1765,38 @@ void CubeMapTextureGLTest::fullImageQuery() { } } -void CubeMapTextureGLTest::fullImageQueryView() { +void CubeMapTextureGLTest::image3DBuffer() { + setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); + + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); + + CubeMapTexture texture; + texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2}) + .setSubImage(0, {}, BufferImage3D{ + PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 6}, + FullPixelStorageData[testCaseInstanceId()].data, + BufferUsage::StaticDraw}); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + BufferImage3D image = texture.image(0, + {FullPixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, + PixelType::UnsignedByte}, BufferUsage::StaticRead); + + MAGNUM_VERIFY_NO_GL_ERROR(); + + CORRADE_COMPARE(image.size(), Vector3i(2, 2, 6)); + const auto imageData = image.buffer().data(); + { + CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa) && FullPixelStorageData[testCaseInstanceId()].storage != PixelStorage{}, + "Mesa drivers can't handle non-default pixel storage for full cubemap image queries."); + CORRADE_COMPARE_AS(Containers::arrayCast(imageData).suffix(FullPixelStorageData[testCaseInstanceId()].offset), + FullPixelStorageData[testCaseInstanceId()].data, TestSuite::Compare::Container); + } +} + +void CubeMapTextureGLTest::image3DQueryView() { setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) @@ -1795,7 +1826,7 @@ void CubeMapTextureGLTest::fullImageQueryView() { } } -void CubeMapTextureGLTest::fullImageQueryViewNullptr() { +void CubeMapTextureGLTest::image3DQueryViewNullptr() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif @@ -1814,7 +1845,7 @@ void CubeMapTextureGLTest::fullImageQueryViewNullptr() { CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::image(): image view is nullptr\n"); } -void CubeMapTextureGLTest::fullImageQueryViewBadSize() { +void CubeMapTextureGLTest::image3DQueryViewBadSize() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif @@ -1834,38 +1865,57 @@ void CubeMapTextureGLTest::fullImageQueryViewBadSize() { CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::image(): expected image view size Vector(2, 2, 6) but got Vector(2, 1, 6)\n"); } -void CubeMapTextureGLTest::fullImageQueryBuffer() { - setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); +void CubeMapTextureGLTest::compressedImage3D() { + setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); + if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); CubeMapTexture texture; - texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2}) - .setSubImage(0, {}, BufferImage3D{ - PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 6}, - FullPixelStorageData[testCaseInstanceId()].data, - BufferUsage::StaticDraw}); + texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}) + .setCompressedSubImage(0, {}, CompressedImageView3D{ + CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 6}, + CompressedFullPixelStorageData[testCaseInstanceId()].data}); - MAGNUM_VERIFY_NO_GL_ERROR(); + { + bool fails(Context::current().detectedDriver() & Context::DetectedDriver::Amd); + CORRADE_EXPECT_FAIL_IF(fails, + "ARB_DSA compressed cubemap APIs are broken on AMD drivers."); - BufferImage3D image = texture.image(0, - {FullPixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, - PixelType::UnsignedByte}, BufferUsage::StaticRead); + MAGNUM_VERIFY_NO_GL_ERROR(); + if(fails) CORRADE_SKIP("Skipping the rest of the test"); + } - MAGNUM_VERIFY_NO_GL_ERROR(); + CompressedImage3D image = texture.compressedImage(0, {CompressedFullPixelStorageData[testCaseInstanceId()].storage}); - CORRADE_COMPARE(image.size(), Vector3i(2, 2, 6)); - const auto imageData = image.buffer().data(); { - CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa) && FullPixelStorageData[testCaseInstanceId()].storage != PixelStorage{}, + #ifdef CORRADE_TARGET_WINDOWS + bool fails(Context::current().detectedDriver() & Context::DetectedDriver::IntelWindows); + CORRADE_EXPECT_FAIL_IF(fails, + "ARB_DSA compressed cubemap APIs are broken on Intel Windows drivers."); + #endif + + MAGNUM_VERIFY_NO_GL_ERROR(); + #ifdef CORRADE_TARGET_WINDOWS + if(fails) CORRADE_SKIP("Skipping the rest of the test"); + #endif + } + + CORRADE_COMPARE(image.size(), (Vector3i{4, 4, 6})); + { + CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa) && CompressedFullPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{}, "Mesa drivers can't handle non-default pixel storage for full cubemap image queries."); - CORRADE_COMPARE_AS(Containers::arrayCast(imageData).suffix(FullPixelStorageData[testCaseInstanceId()].offset), - FullPixelStorageData[testCaseInstanceId()].data, TestSuite::Compare::Container); + CORRADE_COMPARE_AS(Containers::arrayCast(image.data()).suffix(CompressedFullPixelStorageData[testCaseInstanceId()].offset), + CompressedFullPixelStorageData[testCaseInstanceId()].data, + TestSuite::Compare::Container); } } -void CubeMapTextureGLTest::compressedFullImageQuery() { +void CubeMapTextureGLTest::compressedImage3DBuffer() { setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) @@ -1877,9 +1927,10 @@ void CubeMapTextureGLTest::compressedFullImageQuery() { CubeMapTexture texture; texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}) - .setCompressedSubImage(0, {}, CompressedImageView3D{ + .setCompressedSubImage(0, {}, CompressedBufferImage3D{ CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 6}, - CompressedFullPixelStorageData[testCaseInstanceId()].data}); + CompressedFullPixelStorageData[testCaseInstanceId()].data, + BufferUsage::StaticDraw}); { bool fails(Context::current().detectedDriver() & Context::DetectedDriver::Amd); @@ -1890,7 +1941,7 @@ void CubeMapTextureGLTest::compressedFullImageQuery() { if(fails) CORRADE_SKIP("Skipping the rest of the test"); } - CompressedImage3D image = texture.compressedImage(0, {CompressedFullPixelStorageData[testCaseInstanceId()].storage}); + CompressedBufferImage3D image = texture.compressedImage(0, {CompressedFullPixelStorageData[testCaseInstanceId()].storage}, BufferUsage::StaticRead); { #ifdef CORRADE_TARGET_WINDOWS @@ -1906,16 +1957,17 @@ void CubeMapTextureGLTest::compressedFullImageQuery() { } CORRADE_COMPARE(image.size(), (Vector3i{4, 4, 6})); + const auto imageData = image.buffer().data(); { CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa) && CompressedFullPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{}, "Mesa drivers can't handle non-default pixel storage for full cubemap image queries."); - CORRADE_COMPARE_AS(Containers::arrayCast(image.data()).suffix(CompressedFullPixelStorageData[testCaseInstanceId()].offset), + CORRADE_COMPARE_AS(Containers::arrayCast(imageData).suffix(CompressedFullPixelStorageData[testCaseInstanceId()].offset), CompressedFullPixelStorageData[testCaseInstanceId()].data, TestSuite::Compare::Container); } } -void CubeMapTextureGLTest::compressedFullImageQueryView() { +void CubeMapTextureGLTest::compressedImage3DQueryView() { setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); if(!Context::current().isExtensionSupported()) @@ -1967,7 +2019,7 @@ void CubeMapTextureGLTest::compressedFullImageQueryView() { } } -void CubeMapTextureGLTest::compressedFullImageQueryViewNullptr() { +void CubeMapTextureGLTest::compressedImage3DQueryViewNullptr() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif @@ -1988,7 +2040,7 @@ void CubeMapTextureGLTest::compressedFullImageQueryViewNullptr() { CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): image view is nullptr\n"); } -void CubeMapTextureGLTest::compressedFullImageQueryViewBadSize() { +void CubeMapTextureGLTest::compressedImage3DQueryViewBadSize() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif @@ -2010,7 +2062,7 @@ void CubeMapTextureGLTest::compressedFullImageQueryViewBadSize() { CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view size Vector(4, 4, 6) but got Vector(4, 8, 6)\n"); } -void CubeMapTextureGLTest::compressedFullImageQueryViewBadDataSize() { +void CubeMapTextureGLTest::compressedImage3DQueryViewBadDataSize() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif @@ -2032,7 +2084,7 @@ void CubeMapTextureGLTest::compressedFullImageQueryViewBadDataSize() { CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view data size 96 bytes but got 95\n"); } -void CubeMapTextureGLTest::compressedFullImageQueryViewBadFormat() { +void CubeMapTextureGLTest::compressedImage3DQueryViewBadFormat() { #ifdef CORRADE_NO_ASSERT CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif @@ -2053,58 +2105,6 @@ void CubeMapTextureGLTest::compressedFullImageQueryViewBadFormat() { texture.compressedImage(0, image); CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::compressedImage(): expected image view format GL::CompressedPixelFormat::RGBAS3tcDxt3 but got GL::CompressedPixelFormat::RGBAS3tcDxt1\n"); } - -void CubeMapTextureGLTest::compressedFullImageQueryBuffer() { - setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); - - if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); - if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::EXT::texture_compression_s3tc::string() << "is not supported."); - if(CompressedPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{} && !Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::compressed_texture_pixel_storage::string() << "is not supported."); - - CubeMapTexture texture; - texture.setStorage(1, TextureFormat::CompressedRGBAS3tcDxt3, Vector2i{4}) - .setCompressedSubImage(0, {}, CompressedBufferImage3D{ - CompressedPixelFormat::RGBAS3tcDxt3, {4, 4, 6}, - CompressedFullPixelStorageData[testCaseInstanceId()].data, - BufferUsage::StaticDraw}); - - { - bool fails(Context::current().detectedDriver() & Context::DetectedDriver::Amd); - CORRADE_EXPECT_FAIL_IF(fails, - "ARB_DSA compressed cubemap APIs are broken on AMD drivers."); - - MAGNUM_VERIFY_NO_GL_ERROR(); - if(fails) CORRADE_SKIP("Skipping the rest of the test"); - } - - CompressedBufferImage3D image = texture.compressedImage(0, {CompressedFullPixelStorageData[testCaseInstanceId()].storage}, BufferUsage::StaticRead); - - { - #ifdef CORRADE_TARGET_WINDOWS - bool fails(Context::current().detectedDriver() & Context::DetectedDriver::IntelWindows); - CORRADE_EXPECT_FAIL_IF(fails, - "ARB_DSA compressed cubemap APIs are broken on Intel Windows drivers."); - #endif - - MAGNUM_VERIFY_NO_GL_ERROR(); - #ifdef CORRADE_TARGET_WINDOWS - if(fails) CORRADE_SKIP("Skipping the rest of the test"); - #endif - } - - CORRADE_COMPARE(image.size(), (Vector3i{4, 4, 6})); - const auto imageData = image.buffer().data(); - { - CORRADE_EXPECT_FAIL_IF((Context::current().detectedDriver() & Context::DetectedDriver::Mesa) && CompressedFullPixelStorageData[testCaseInstanceId()].storage != CompressedPixelStorage{}, - "Mesa drivers can't handle non-default pixel storage for full cubemap image queries."); - CORRADE_COMPARE_AS(Containers::arrayCast(imageData).suffix(CompressedFullPixelStorageData[testCaseInstanceId()].offset), - CompressedFullPixelStorageData[testCaseInstanceId()].data, - TestSuite::Compare::Container); - } -} #endif void CubeMapTextureGLTest::generateMipmap() { From 61f8b5da57ee5632f3d2e5abd2bba182c4fd615c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 12 Apr 2021 12:17:16 +0200 Subject: [PATCH 130/161] GL: enable cube map 3D image up/download on all platforms. There were slice-by-slice workarounds for certain drivers already, so why not reuse them to make this functionality available everywhere. --- doc/changelog.dox | 7 +++ src/Magnum/GL/CubeMapTexture.cpp | 14 ++++- src/Magnum/GL/CubeMapTexture.h | 52 +++++++++++++------ src/Magnum/GL/Implementation/TextureState.cpp | 19 ++++--- src/Magnum/GL/Implementation/TextureState.h | 2 +- src/Magnum/GL/Test/CubeMapTextureGLTest.cpp | 45 ++++++++++------ 6 files changed, 97 insertions(+), 42 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 80f29afce..637121113 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -220,6 +220,13 @@ See also: - The @ref GL::Context class got significantly optimized in terms of compile time, header size and runtime as well, significantly reducing the amount of allocations done at startup. +- To make working with cube map images easier, + @ref GL::CubeMapTexture::setSubImage() and + @ref GL::CubeMapTexture::subImage() taking 3D images are now exposed on all + platforms, not just desktop OpenGL 4.5+, with a fall back to slice-by-slice + upload/download where needed. The compressed variant is still only GL 4.5+, + as that needs the @ref CompressedImageView APIs to be aware of compression + format properties, which isn't implemented yet. - Added @ref GL::Framebuffer::Status::IncompleteDimensions for ES2. This enum isn't available on ES3 or desktop GL, but NVidia drivers are known to emit it, which is why it got added. diff --git a/src/Magnum/GL/CubeMapTexture.cpp b/src/Magnum/GL/CubeMapTexture.cpp index 9651f4ba0..c763dd346 100644 --- a/src/Magnum/GL/CubeMapTexture.cpp +++ b/src/Magnum/GL/CubeMapTexture.cpp @@ -493,16 +493,24 @@ CompressedBufferImage3D CubeMapTexture::compressedSubImage(const Int level, cons compressedSubImage(level, range, image, usage); return std::move(image); } +#endif CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, const ImageView3D& image) { createIfNotAlready(); + #ifndef MAGNUM_TARGET_GLES2 Buffer::unbindInternal(Buffer::TargetHint::PixelUnpack); + #endif Context::current().state().renderer.applyPixelStorageUnpack(image.storage()); - (this->*Context::current().state().texture.cubeSubImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data(), image.storage()); + (this->*Context::current().state().texture.cubeSubImage3DImplementation)(level, offset, image.size(), pixelFormat(image.format()), pixelType(image.format(), image.formatExtra()), image.data() + #ifdef MAGNUM_TARGET_GLES2 + + Magnum::Implementation::pixelStorageSkipOffset(image) + #endif + , image.storage()); return *this; } +#ifndef MAGNUM_TARGET_GLES2 CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& offset, BufferImage3D& image) { createIfNotAlready(); @@ -511,7 +519,9 @@ CubeMapTexture& CubeMapTexture::setSubImage(const Int level, const Vector3i& off (this->*Context::current().state().texture.cubeSubImage3DImplementation)(level, offset, image.size(), image.format(), image.type(), nullptr, image.storage()); return *this; } +#endif +#ifndef MAGNUM_TARGET_GLES CubeMapTexture& CubeMapTexture::setCompressedSubImage(const Int level, const Vector3i& offset, const CompressedImageView3D& image) { createIfNotAlready(); @@ -689,13 +699,13 @@ void CubeMapTexture::subImageImplementationDSASliceBySlice(const GLint level, co for(Int i = 0; i != size.z(); ++i) subImageImplementationDSA(level, {offset.xy(), offset.z() + i}, {size.xy(), 1}, format, type, static_cast(data) + stride*i, storage); } +#endif void CubeMapTexture::subImageImplementationSliceBySlice(const GLint level, const Vector3i& offset, const Vector3i& size, const PixelFormat format, const PixelType type, const GLvoid* const data, const PixelStorage& storage) { const std::size_t stride = std::get<1>(storage.dataProperties(pixelSize(format, type), size)).xy().product(); for(Int i = 0; i != size.z(); ++i) subImageImplementationDefault(CubeMapCoordinate(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i), level, offset.xy(), size.xy(), format, type, static_cast(data) + stride*i); } -#endif void CubeMapTexture::subImageImplementationDefault(const CubeMapCoordinate coordinate, const GLint level, const Vector2i& offset, const Vector2i& size, const PixelFormat format, const PixelType type, const GLvoid* const data) { bindInternal(); diff --git a/src/Magnum/GL/CubeMapTexture.h b/src/Magnum/GL/CubeMapTexture.h index 38aec069b..9e0f6ff3b 100644 --- a/src/Magnum/GL/CubeMapTexture.h +++ b/src/Magnum/GL/CubeMapTexture.h @@ -559,10 +559,19 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * @ref imageSize(). The storage is not reallocated if it is large * enough to contain the new data. * - * The operation is protected from buffer overflow. - * @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter} with - * @def_gl{TEXTURE_WIDTH}, @def_gl{TEXTURE_HEIGHT}, then - * @fn_gl{PixelStore}, then @fn_gl2_keyword{GetTextureImage,GetTexImage} + * If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is + * not available, the texture is bound before the operation (if not + * already) and the image is downloaded slice by slice. If either + * @gl_extension{ARB,get_texture_sub_image} or + * @gl_extension{ARB,robustness} is available, the operation is + * protected from buffer overflow. + * @see @fn_gl2{GetTextureLevelParameter,GetTexLevelParameter}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl{GetTexLevelParameter} with @def_gl{TEXTURE_WIDTH}, + * @def_gl{TEXTURE_HEIGHT}, then @fn_gl{PixelStore}, then + * @fn_gl2_keyword{GetTextureImage,GetTexImage}, + * @fn_gl_extension_keyword{GetnTexImage,ARB,robustness}, + * eventually @fn_gl_keyword{GetTexImage} * @requires_gl45 Extension @gl_extension{ARB,direct_state_access} * @requires_gl Texture image queries are not available in OpenGL ES or * WebGL. See @ref Framebuffer::read() or @ref DebugTools::textureSubImage() @@ -1024,7 +1033,6 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { } #endif - #ifndef MAGNUM_TARGET_GLES /** * @brief Set image subdata * @param level Mip level @@ -1033,29 +1041,41 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { * @ref Trade::ImageData3D * @return Reference to self (for method chaining) * - * @see @ref setStorage(), @fn_gl2{TextureSubImage3D,TexSubImage3D} - * @requires_gl45 Extension @gl_extension{ARB,direct_state_access} - * @requires_gl In OpenGL ES and WebGL you need to set image for each - * face separately. + * If @gl_extension{ARB,direct_state_access} (part of OpenGL 4.5) is + * not available, the texture is bound before the operation (if not + * already) and the image is uploaded slice by slice. + * @see @ref setStorage(), @fn_gl2{TextureSubImage3D,TexSubImage3D}, + * eventually @fn_gl{ActiveTexture}, @fn_gl{BindTexture} and + * @fn_gl_keyword{TexSubImage2D} + * @requires_gles30 Extension @gl_extension{EXT,unpack_subimage}/ + * @gl_extension{NV,pack_subimage} in OpenGL ES 2.0 if + * @ref PixelStorage::rowLength() is set to a non-zero value. + * @requires_webgl20 Non-zero @ref PixelStorage::rowLength() is not + * supported in WebGL 1.0. */ CubeMapTexture& setSubImage(Int level, const Vector3i& offset, const ImageView3D& image); + #ifndef MAGNUM_TARGET_GLES2 /** @overload - * @requires_gl45 Extension @gl_extension{ARB,direct_state_access} - * @requires_gl In OpenGL ES and WebGL you need to set image for each - * face separately. + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. */ CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D& image); /** @overload - * @requires_gl45 Extension @gl_extension{ARB,direct_state_access} - * @requires_gl In OpenGL ES and WebGL you need to set image for each - * face separately. + * @requires_gles30 Pixel buffer objects are not available in OpenGL ES + * 2.0. + * @requires_webgl20 Pixel buffer objects are not available in WebGL + * 1.0. */ CubeMapTexture& setSubImage(Int level, const Vector3i& offset, BufferImage3D&& image) { return setSubImage(level, offset, image); } + #endif + #ifndef MAGNUM_TARGET_GLES /** * @brief Set compressed image subdata * @param level Mip level @@ -1248,8 +1268,8 @@ class MAGNUM_GL_EXPORT CubeMapTexture: public AbstractTexture { #ifndef MAGNUM_TARGET_GLES void MAGNUM_GL_LOCAL subImageImplementationDSA(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&); void MAGNUM_GL_LOCAL subImageImplementationDSASliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&); - void MAGNUM_GL_LOCAL subImageImplementationSliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&); #endif + void MAGNUM_GL_LOCAL subImageImplementationSliceBySlice(GLint level, const Vector3i& offset, const Vector3i& size, PixelFormat format, PixelType type, const GLvoid* data, const PixelStorage&); void MAGNUM_GL_LOCAL subImageImplementationDefault(CubeMapCoordinate coordinate, GLint level, const Vector2i& offset, const Vector2i& size, PixelFormat format, PixelType type, const GLvoid* data); #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/GL/Implementation/TextureState.cpp b/src/Magnum/GL/Implementation/TextureState.cpp index 374ba2ff7..6f477557b 100644 --- a/src/Magnum/GL/Implementation/TextureState.cpp +++ b/src/Magnum/GL/Implementation/TextureState.cpp @@ -348,6 +348,9 @@ TextureState::TextureState(Context& context, getCubeImage3DImplementation = &CubeMapTexture::getImageImplementationSliceBySlice; else #endif + if(context.isExtensionSupported()) { + getCubeImage3DImplementation = &CubeMapTexture::getImageImplementationDSA; + } else { getCubeImage3DImplementation = &CubeMapTexture::getImageImplementationSliceBySlice; } #endif @@ -500,14 +503,14 @@ TextureState::TextureState(Context& context, /* SVGA3D and Intel workaround for cube map texture upload. Overrides the DSA / non-DSA function pointers set above. */ if((context.detectedDriver() & Context::DetectedDriver::Svga3D) && - !context.isDriverWorkaroundDisabled("svga3d-texture-upload-slice-by-slice"_s)) { - if(context.isExtensionSupported()) { - cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationDSASliceBySlice; - } else { - cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationSliceBySlice; - } + context.isExtensionSupported() && + !context.isDriverWorkaroundDisabled("svga3d-texture-upload-slice-by-slice"_s) + ) { + cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationDSASliceBySlice; } else if((context.detectedDriver() & Context::DetectedDriver::IntelWindows) && - !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps"_s)) { + context.isExtensionSupported() && + !context.isDriverWorkaroundDisabled("intel-windows-broken-dsa-for-cubemaps"_s) + ) { cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationSliceBySlice; } #ifdef CORRADE_TARGET_WINDOWS @@ -523,10 +526,10 @@ TextureState::TextureState(Context& context, else if(context.isExtensionSupported()) { cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationDSA; } else + #endif { cubeSubImage3DImplementation = &CubeMapTexture::subImageImplementationSliceBySlice; } - #endif #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) if(!context.isDriverWorkaroundDisabled("apple-buffer-texture-unbind-on-buffer-modify"_s)) { diff --git a/src/Magnum/GL/Implementation/TextureState.h b/src/Magnum/GL/Implementation/TextureState.h index a0477a93f..686fd4d18 100644 --- a/src/Magnum/GL/Implementation/TextureState.h +++ b/src/Magnum/GL/Implementation/TextureState.h @@ -125,8 +125,8 @@ struct TextureState { void(CubeMapTexture::*getCubeImage3DImplementation)(GLint, const Vector3i&, PixelFormat, PixelType, std::size_t, GLvoid*, const PixelStorage&); void(CubeMapTexture::*getCompressedCubeImage3DImplementation)(GLint, const Vector2i&, std::size_t, std::size_t, GLvoid*); void(CubeMapTexture::*getCompressedCubeImageImplementation)(CubeMapCoordinate, GLint, const Vector2i&, std::size_t, GLvoid*); - void(CubeMapTexture::*cubeSubImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&); #endif + void(CubeMapTexture::*cubeSubImage3DImplementation)(GLint, const Vector3i&, const Vector3i&, PixelFormat, PixelType, const GLvoid*, const PixelStorage&); void(CubeMapTexture::*cubeSubImageImplementation)(CubeMapCoordinate, GLint, const Vector2i&, const Vector2i&, PixelFormat, PixelType, const GLvoid*); void(CubeMapTexture::*cubeCompressedSubImageImplementation)(CubeMapCoordinate, GLint, const Vector2i&, const Vector2i&, CompressedPixelFormat, const GLvoid*, GLsizei); diff --git a/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp b/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp index 41f78f076..d21cdb009 100644 --- a/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp +++ b/src/Magnum/GL/Test/CubeMapTextureGLTest.cpp @@ -128,15 +128,21 @@ struct CubeMapTextureGLTest: OpenGLTester { void compressedSubImageQueryBuffer(); #endif - #ifndef MAGNUM_TARGET_GLES void image3D(); + #ifndef MAGNUM_TARGET_GLES2 void image3DBuffer(); + #endif + #ifndef MAGNUM_TARGET_GLES void image3DQueryView(); void image3DQueryViewNullptr(); void image3DQueryViewBadSize(); + #endif + #ifndef MAGNUM_TARGET_GLES void compressedImage3D(); + #ifndef MAGNUM_TARGET_GLES2 void compressedImage3DBuffer(); + #endif void compressedImage3DQueryView(); void compressedImage3DQueryViewNullptr(); void compressedImage3DQueryViewBadSize(); @@ -216,7 +222,6 @@ const struct { #endif }; -#ifndef MAGNUM_TARGET_GLES constexpr UnsignedByte FullData[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -253,6 +258,7 @@ const struct { #endif }; +#ifndef MAGNUM_TARGET_GLES /* Just 4x4 0x00 - 0x3f compressed using RGBA DXT3 by the driver, repeated six times */ constexpr UnsignedByte CompressedFullData[]{ @@ -348,13 +354,17 @@ CubeMapTextureGLTest::CubeMapTextureGLTest() { &CubeMapTextureGLTest::imageQueryViewBadSize}); #endif - #ifndef MAGNUM_TARGET_GLES addInstancedTests({ &CubeMapTextureGLTest::image3D, + #ifndef MAGNUM_TARGET_GLES2 &CubeMapTextureGLTest::image3DBuffer, - &CubeMapTextureGLTest::image3DQueryView}, - Containers::arraySize(FullPixelStorageData)); + #endif + #ifndef MAGNUM_TARGET_GLES + &CubeMapTextureGLTest::image3DQueryView + #endif + }, Containers::arraySize(FullPixelStorageData)); + #ifndef MAGNUM_TARGET_GLES addTests({&CubeMapTextureGLTest::image3DQueryViewNullptr, &CubeMapTextureGLTest::image3DQueryViewBadSize}); #endif @@ -1735,21 +1745,24 @@ void CubeMapTextureGLTest::compressedSubImageQueryBuffer() { } #endif -#ifndef MAGNUM_TARGET_GLES void CubeMapTextureGLTest::image3D() { setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); - if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); + #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) + constexpr TextureFormat format = TextureFormat::RGBA8; + #else + constexpr TextureFormat format = TextureFormat::RGBA; + #endif CubeMapTexture texture; - texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2, 2}) + texture.setStorage(1, format, Vector2i{2, 2}) .setSubImage(0, {}, ImageView3D{ PixelFormat::RGBA, PixelType::UnsignedByte, {2, 2, 6}, FullPixelStorageData[testCaseInstanceId()].data}); MAGNUM_VERIFY_NO_GL_ERROR(); + #ifndef MAGNUM_TARGET_GLES Image3D image = texture.image(0, {FullPixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, PixelType::UnsignedByte}); @@ -1763,14 +1776,13 @@ void CubeMapTextureGLTest::image3D() { FullPixelStorageData[testCaseInstanceId()].data, TestSuite::Compare::Container); } + #endif } +#ifndef MAGNUM_TARGET_GLES2 void CubeMapTextureGLTest::image3DBuffer() { setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); - if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); - CubeMapTexture texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2}) .setSubImage(0, {}, BufferImage3D{ @@ -1780,6 +1792,7 @@ void CubeMapTextureGLTest::image3DBuffer() { MAGNUM_VERIFY_NO_GL_ERROR(); + #ifndef MAGNUM_TARGET_GLES BufferImage3D image = texture.image(0, {FullPixelStorageData[testCaseInstanceId()].storage, PixelFormat::RGBA, PixelType::UnsignedByte}, BufferUsage::StaticRead); @@ -1794,14 +1807,14 @@ void CubeMapTextureGLTest::image3DBuffer() { CORRADE_COMPARE_AS(Containers::arrayCast(imageData).suffix(FullPixelStorageData[testCaseInstanceId()].offset), FullPixelStorageData[testCaseInstanceId()].data, TestSuite::Compare::Container); } + #endif } +#endif +#ifndef MAGNUM_TARGET_GLES void CubeMapTextureGLTest::image3DQueryView() { setTestCaseDescription(FullPixelStorageData[testCaseInstanceId()].name); - if(!Context::current().isExtensionSupported()) - CORRADE_SKIP(Extensions::ARB::direct_state_access::string() << "is not supported."); - CubeMapTexture texture; texture.setStorage(1, TextureFormat::RGBA8, Vector2i{2, 2}) .setSubImage(0, {}, ImageView3D{ @@ -1864,7 +1877,9 @@ void CubeMapTextureGLTest::image3DQueryViewBadSize() { texture.image(0, image); CORRADE_COMPARE(out.str(), "GL::CubeMapTexture::image(): expected image view size Vector(2, 2, 6) but got Vector(2, 1, 6)\n"); } +#endif +#ifndef MAGNUM_TARGET_GLES void CubeMapTextureGLTest::compressedImage3D() { setTestCaseDescription(CompressedFullPixelStorageData[testCaseInstanceId()].name); From fe4d55f30d9c8bbe2f6bef4478788f5b58abdbd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Apr 2021 15:19:54 +0200 Subject: [PATCH 131/161] DebugTools: missing forward declaration for FrameProfiler. And the old Profiler wasn't properly marked as deprecated there. --- src/Magnum/DebugTools/DebugTools.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Magnum/DebugTools/DebugTools.h b/src/Magnum/DebugTools/DebugTools.h index 5f5c4c792..5bb47690f 100644 --- a/src/Magnum/DebugTools/DebugTools.h +++ b/src/Magnum/DebugTools/DebugTools.h @@ -31,12 +31,21 @@ #include "Magnum/Types.h" +#ifdef MAGNUM_BUILD_DEPRECATED +#include +#endif + namespace Magnum { namespace DebugTools { #ifndef DOXYGEN_GENERATING_OUTPUT -class Profiler; +#ifdef MAGNUM_BUILD_DEPRECATED +class CORRADE_DEPRECATED("use FrameProfiler instead") Profiler; +#endif +class FrameProfiler; #ifdef MAGNUM_TARGET_GL +class GLFrameProfiler; + template class ForceRenderer; typedef ForceRenderer<2> ForceRenderer2D; typedef ForceRenderer<3> ForceRenderer3D; From d3f83b6665262493fc65e2c7917bee079b561169 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Apr 2021 17:23:54 +0200 Subject: [PATCH 132/161] Vk: the configure file is needed for non-Vk tests as well. --- src/Magnum/Vk/Test/CMakeLists.txt | 63 +++++++++++++++++-------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/Magnum/Vk/Test/CMakeLists.txt b/src/Magnum/Vk/Test/CMakeLists.txt index fbe926370..2c21967f2 100644 --- a/src/Magnum/Vk/Test/CMakeLists.txt +++ b/src/Magnum/Vk/Test/CMakeLists.txt @@ -24,6 +24,40 @@ # DEALINGS IN THE SOFTWARE. # +# Inputs to configure.h needed only by Vulkan tests +if(BUILD_VK_TESTS) + # Otherwise CMake complains that Corrade::PluginManager is not found, wtf + find_package(Corrade REQUIRED PluginManager) + + if(CORRADE_TARGET_ANDROID) + set(VK_TEST_DIR ".") + else() + set(VK_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + endif() + + # CMake before 3.8 has broken $ expressions for iOS (see + # https://gitlab.kitware.com/cmake/cmake/merge_requests/404) and since + # Corrade doesn't support dynamic plugins on iOS, this sorta works around + # that. Should be revisited when updating Travis to newer Xcode (xcode7.3 + # has CMake 3.6). + if(NOT BUILD_PLUGINS_STATIC) + if(WITH_ANYIMAGEIMPORTER) + set(ANYIMAGEIMPORTER_PLUGIN_FILENAME $) + endif() + if(WITH_TGAIMPORTER) + set(TGAIMPORTER_PLUGIN_FILENAME $) + endif() + endif() +endif() + +# The file is needed by VkShaderTest as well, so it's created always, not just +# for BUILD_VK_TESTS. First replace ${} variables, then $<> generator +# expressions. +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake + ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in) +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$/configure.h + INPUT ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in) + corrade_add_test(VkBufferTest BufferTest.cpp LIBRARIES MagnumVkTestLib) corrade_add_test(VkCommandBufferTest CommandBufferTest.cpp LIBRARIES MagnumVk) corrade_add_test(VkCommandPoolTest CommandPoolTest.cpp LIBRARIES MagnumVk) @@ -168,35 +202,6 @@ set_target_properties( PROPERTIES FOLDER "Magnum/Vk/Test") if(BUILD_VK_TESTS) - # Otherwise CMake complains that Corrade::PluginManager is not found, wtf - find_package(Corrade REQUIRED PluginManager) - - if(CORRADE_TARGET_ANDROID) - set(VK_TEST_DIR ".") - else() - set(VK_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - endif() - - # CMake before 3.8 has broken $ expressions for iOS (see - # https://gitlab.kitware.com/cmake/cmake/merge_requests/404) and since - # Corrade doesn't support dynamic plugins on iOS, this sorta works around - # that. Should be revisited when updating Travis to newer Xcode (xcode7.3 - # has CMake 3.6). - if(NOT BUILD_PLUGINS_STATIC) - if(WITH_ANYIMAGEIMPORTER) - set(ANYIMAGEIMPORTER_PLUGIN_FILENAME $) - endif() - if(WITH_TGAIMPORTER) - set(TGAIMPORTER_PLUGIN_FILENAME $) - endif() - endif() - - # First replace ${} variables, then $<> generator expressions - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in) - file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$/configure.h - INPUT ${CMAKE_CURRENT_BINARY_DIR}/configure.h.in) - corrade_add_test(VkBufferVkTest BufferVkTest.cpp LIBRARIES MagnumVkTestLib MagnumVulkanTester) corrade_add_test(VkCommandBufferVkTest CommandBufferVkTest.cpp LIBRARIES MagnumVulkanTester) corrade_add_test(VkCommandPoolVkTest CommandPoolVkTest.cpp LIBRARIES MagnumVulkanTester) From c0d64b913edcd93e6eb29db226af6c8fc6a0495b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 24 Apr 2021 19:49:58 +0200 Subject: [PATCH 133/161] GL: this Buffer::setStorage() overload wasn't implemented. Also test it properly and add a check for extension availability. Sigh, seems like nobody ran this test on an Apple device since this thing got added in 75d238f50bd377caf56d1f7a9170b8921d9a7ee5 ... --- src/Magnum/GL/Buffer.cpp | 4 ++++ src/Magnum/GL/Test/BufferGLTest.cpp | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/Magnum/GL/Buffer.cpp b/src/Magnum/GL/Buffer.cpp index 00f4d8449..3af14aab6 100644 --- a/src/Magnum/GL/Buffer.cpp +++ b/src/Magnum/GL/Buffer.cpp @@ -310,6 +310,10 @@ Buffer& Buffer::setStorage(const Containers::ArrayView data, const S (this->*Context::current().state().buffer.storageImplementation)(data, flags); return *this; } + +Buffer& Buffer::setStorage(const std::size_t size, const StorageFlags flags) { + return setStorage({nullptr, size}, flags); +} #endif Int Buffer::size() { diff --git a/src/Magnum/GL/Test/BufferGLTest.cpp b/src/Magnum/GL/Test/BufferGLTest.cpp index 873ce69b7..830da5998 100644 --- a/src/Magnum/GL/Test/BufferGLTest.cpp +++ b/src/Magnum/GL/Test/BufferGLTest.cpp @@ -56,6 +56,7 @@ struct BufferGLTest: OpenGLTester { #ifndef MAGNUM_TARGET_GLES void storage(); + void storagePreinitialized(); #endif void data(); @@ -87,6 +88,7 @@ BufferGLTest::BufferGLTest() { #ifndef MAGNUM_TARGET_GLES &BufferGLTest::storage, + &BufferGLTest::storagePreinitialized, #endif &BufferGLTest::data, @@ -254,6 +256,26 @@ void BufferGLTest::bindRange() { #ifndef MAGNUM_TARGET_GLES void BufferGLTest::storage() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::buffer_storage::string() << "is not supported."); + + Buffer buffer; + + constexpr Int data[] = {2, 7, 5, 13, 25}; + + buffer.setStorage(sizeof(data), Buffer::StorageFlag::DynamicStorage) + .setSubData(0, data); + MAGNUM_VERIFY_NO_GL_ERROR(); + + CORRADE_COMPARE_AS(Containers::arrayCast(buffer.data()), + Containers::arrayView(data), + TestSuite::Compare::Container); +} + +void BufferGLTest::storagePreinitialized() { + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::ARB::buffer_storage::string() << "is not supported."); + Buffer buffer; constexpr Int data[] = {2, 7, 5, 13, 25}; From 2f24199ed7008b2930972b9f3bf48cdef5b8b836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 24 Apr 2021 20:07:18 +0200 Subject: [PATCH 134/161] GL: improve message for the common mesh assert in multi-draw. In my case I was using a dangling MeshView reference there, and it was hard to debug without these. --- src/Magnum/GL/AbstractShaderProgram.cpp | 6 +++--- src/Magnum/GL/Test/MeshGLTest.cpp | 20 ++++++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Magnum/GL/AbstractShaderProgram.cpp b/src/Magnum/GL/AbstractShaderProgram.cpp index 5f228b827..05685f68e 100644 --- a/src/Magnum/GL/AbstractShaderProgram.cpp +++ b/src/Magnum/GL/AbstractShaderProgram.cpp @@ -386,9 +386,9 @@ void AbstractShaderProgram::draw(Containers::ArrayViewget()._original.get(); - for(MeshView& mesh: meshes) - CORRADE_ASSERT(&mesh._original.get() == original, "GL::AbstractShaderProgram::draw(): all meshes must be views of the same original mesh", ); + const Mesh* original = &*meshes.front()->_original; + for(std::size_t i = 0; i != meshes.size(); ++i) + CORRADE_ASSERT(&*meshes[i]->_original == original, "GL::AbstractShaderProgram::draw(): all meshes must be views of the same original mesh, expected" << original << "but got" << &*meshes[i]->_original << "at index" << i, ); #endif #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/GL/Test/MeshGLTest.cpp b/src/Magnum/GL/Test/MeshGLTest.cpp index df17de288..f58b3a598 100644 --- a/src/Magnum/GL/Test/MeshGLTest.cpp +++ b/src/Magnum/GL/Test/MeshGLTest.cpp @@ -25,6 +25,7 @@ #include #include +#include #include "Magnum/Image.h" #include "Magnum/Mesh.h" @@ -189,6 +190,7 @@ struct MeshGLTest: OpenGLTester { #ifdef MAGNUM_TARGET_GLES void multiDrawBaseVertexNoExtensionAvailable(); #endif + void multiDrawDifferentMeshes(); }; MeshGLTest::MeshGLTest() { @@ -335,9 +337,9 @@ MeshGLTest::MeshGLTest() { &MeshGLTest::multiDrawBaseVertex, #endif #ifdef MAGNUM_TARGET_GLES - &MeshGLTest::multiDrawBaseVertexNoExtensionAvailable + &MeshGLTest::multiDrawBaseVertexNoExtensionAvailable, #endif - }); + &MeshGLTest::multiDrawDifferentMeshes}); } using namespace Math::Literals; @@ -3456,6 +3458,20 @@ void MeshGLTest::multiDrawBaseVertexNoExtensionAvailable() { } #endif +void MeshGLTest::multiDrawDifferentMeshes() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + + Mesh a, b; + MeshView viewA{a}, viewB{b}; + + std::ostringstream out; + Error redirectError{&out}; + MultipleShader{}.draw({viewA, viewB}); + CORRADE_COMPARE(out.str(), Utility::formatString("GL::AbstractShaderProgram::draw(): all meshes must be views of the same original mesh, expected 0x{:x} but got 0x{:x} at index 1\n", reinterpret_cast(&a), reinterpret_cast(&b))); +} + }}}} CORRADE_TEST_MAIN(Magnum::GL::Test::MeshGLTest) From d44514b60f2d9b6c02ba195ee3da906d20474642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 24 Apr 2021 20:35:18 +0200 Subject: [PATCH 135/161] GL: properly skip a test on a no-assert build. --- src/Magnum/GL/Test/MeshGLTest.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Magnum/GL/Test/MeshGLTest.cpp b/src/Magnum/GL/Test/MeshGLTest.cpp index f58b3a598..7024ce347 100644 --- a/src/Magnum/GL/Test/MeshGLTest.cpp +++ b/src/Magnum/GL/Test/MeshGLTest.cpp @@ -3364,6 +3364,10 @@ void MeshGLTest::multiDrawIndexed() { } void MeshGLTest::multiDrawInstanced() { + #ifdef CORRADE_NO_ASSERT + CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); + #endif + Mesh mesh; MeshView view{mesh}; view.setCount(3) From c92782456264572a3131c0572c56fb1715cb4c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 26 Apr 2021 12:04:32 +0200 Subject: [PATCH 136/161] Make it discoverable that Debug etc is brought into the Magnum namespace. --- doc/changelog.dox | 5 +++++ src/Magnum/Magnum.h | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 637121113..9626ca85d 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -648,6 +648,11 @@ See also: @ref platforms-windows "Windows platform docs" (see [mosra/magnum#227](https://github.com/mosra/magnum/issues/227) and [mosra/magnum#439](https://github.com/mosra/magnum/issues/439)) - Various documentation fixes (see [mosra/magnum#492](https://github.com/mosra/magnum/issues/492)) +- @ref Corrade::Utility::Debug and friends were always brought to the ) + @ref Magnum namespace via a @cpp using @ce directive, but this was never + reflected in the docs and thus hidden from users. Now it's shown in the + docs as a set of @ref Debug etc typedefs instead, to make them more + discoverable. @section changelog-2020-06 2020.06 diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 4d68ab0df..2d39b24aa 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -43,11 +43,47 @@ namespace Magnum { /* Bring whole Corrade namespace */ using namespace Corrade; -/* Bring debugging facility from Corrade::Utility namespace */ +#ifdef DOXYGEN_GENERATING_OUTPUT +/** +@brief Alias for debug output + +A shorthand for the fully-qualified name in Corrade. +@see @ref Warning, @ref Error, @ref Fatal, + @ref Corrade::TestSuite::Tester::Debug +*/ +typedef Corrade::Utility::Debug Debug; + +/** +@brief Alias for warning output + +A shorthand for the fully-qualified name in Corrade. +@see @ref Debug, @ref Error, @ref Fatal, + @ref Corrade::TestSuite::Tester::Warning +*/ +typedef Corrade::Utility::Warning Warning; + +/** +@brief Alias for error output + +A shorthand for the fully-qualified name in Corrade. +@see @ref Debug, @ref Warning, @ref Fatal, + @ref Corrade::TestSuite::Tester::Error +*/ +typedef Corrade::Utility::Error Error; + +/** +@brief Alias for fatal output + +A shorthand for the fully-qualified name in Corrade. +@see @ref Debug, @ref Warning, @ref Error +*/ +typedef Corrade::Utility::Fatal Fatal; +#else using Corrade::Utility::Debug; using Corrade::Utility::Warning; using Corrade::Utility::Error; using Corrade::Utility::Fatal; +#endif #ifdef DOXYGEN_GENERATING_OUTPUT /** From 7c14379e377d09e95bbc67c7e35770b5f7abd919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 26 Apr 2021 15:39:46 +0200 Subject: [PATCH 137/161] Trade: ?! here?? why?!! --- src/Magnum/Trade/SceneData.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Magnum/Trade/SceneData.h b/src/Magnum/Trade/SceneData.h index 164c4979a..8a10cfd8f 100644 --- a/src/Magnum/Trade/SceneData.h +++ b/src/Magnum/Trade/SceneData.h @@ -29,7 +29,6 @@ * @brief Class @ref Magnum::Trade::SceneData */ -#include #include #include "Magnum/Types.h" From 90126a4ded3f67846f22cc53061d6d6d91ca54c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 29 Apr 2021 10:28:28 +0200 Subject: [PATCH 138/161] CMake: avoid warnings with CMake 3.10+ and CMAKE_AUTOMOC set. Co-authored-by: Andy Maloney --- CMakeLists.txt | 6 ++++++ doc/changelog.dox | 2 ++ 2 files changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 593c31166..dfa87394c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,12 @@ if(HUNTER_ENABLED) include(${CMAKE_CURRENT_LIST_DIR}/package/hunter/HunterInit.cmake) endif() +# If CMAKE_AUTOMOC is set, all uses of corrade_add_resource() would otherwise +# complain on 3.10 that AUTOMOC is not processing GENERATED files +if(POLICY CMP0071) + cmake_policy(SET CMP0071 NEW) +endif() + project(Magnum CXX) if(HUNTER_ENABLED) diff --git a/doc/changelog.dox b/doc/changelog.dox index 9626ca85d..0f31439ec 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -359,6 +359,8 @@ See also: same effect. See @ref building-cross-android, @ref platforms-android and [mosra/magnum#310](https://github.com/mosra/magnum/issues/310) for more information. +- Suppressing a CMake policy-related warning if the global `CMAKE_AUTOMOC` is + set on CMake 3.10+ (see [mosra/magnum#504](https://github.com/mosra/magnum/pull/504)) @subsection changelog-latest-bugfixes Bug fixes From aeb26aaad46b061438f6ae374bb756b85a70f2ae Mon Sep 17 00:00:00 2001 From: Andy Maloney Date: Thu, 29 Apr 2021 12:43:15 +0200 Subject: [PATCH 139/161] CMake: fix a spelling mistake in WITH_PRIMITIVES option. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dfa87394c..eb365ee5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,7 @@ cmake_dependent_option(WITH_TEXT "Build Text library" ON "NOT WITH_FONTCONVERTER 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) cmake_dependent_option(WITH_GL "Build GL library" ON "NOT WITH_SHADERS;NOT WITH_GL_INFO;NOT WITH_ANDROIDAPPLICATION;NOT WITH_WINDOWLESSIOSAPPLICATION;NOT WITH_CGLCONTEXT;NOT WITH_GLXAPPLICATION;NOT WITH_GLXCONTEXT;NOT WITH_XEGLAPPLICATION;NOT WITH_WINDOWLESSWGLAPPLICATION;NOT WITH_WGLCONTEXT;NOT WITH_WINDOWLESSWINDOWSEGLAPPLICATION;NOT WITH_DISTANCEFIELDCONVERTER" ON) -option(WITH_PRIMITIVES "Builf Primitives library" ON) +option(WITH_PRIMITIVES "Build Primitives library" ON) cmake_dependent_option(TARGET_HEADLESS "Build command-line utilities for use on a headless machines" OFF "WITH_GL" OFF) cmake_dependent_option(TARGET_GL "Build libraries with OpenGL interoperability" ON "WITH_GL" OFF) From 6958f4a413ebe1c24bd8e5dd6ecbded2d2723378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 29 Apr 2021 12:44:27 +0200 Subject: [PATCH 140/161] doc: update credits. --- doc/credits.dox | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/credits.dox b/doc/credits.dox index 5857ac8f9..9bf8b54ba 100644 --- a/doc/credits.dox +++ b/doc/credits.dox @@ -95,6 +95,8 @@ Are the below lists missing your name or something's wrong? @ref Audio::WavImporter "WavAudioImporter" plugin - **Andrew ([\@sheerluck](https://github.com/sheerluck))** --- Gentoo package fixes +- **Andy Maloney** ([\@asmaloney](https://github.com/asmaloney)) --- CMake + fixes - **Andy Somogyi** ([\@andysomogyi](https://github.com/andysomogyi)) --- bugreports, API design improvement suggestions - **[\@ArEnSc](https://github.com/ArEnSc)** --- initial implementation of From ec19c25e46aede76ccfd4b0938d3b6f8c66f3319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 30 Apr 2021 15:01:41 +0200 Subject: [PATCH 141/161] Adapt to Corrade changes. --- doc/generated/colormaps.cpp | 2 +- src/Magnum/Animation/Player.hpp | 4 +- src/Magnum/Animation/Test/Benchmark.cpp | 4 +- src/Magnum/Animation/Test/TrackTest.cpp | 12 ++--- src/Magnum/Animation/Track.h | 12 ++--- .../Audio/Test/AbstractImporterTest.cpp | 2 +- src/Magnum/DebugTools/CompareImage.cpp | 4 +- src/Magnum/DebugTools/FrameProfiler.cpp | 14 +++--- .../DebugTools/Test/CompareImageTest.cpp | 8 +-- .../DebugTools/Test/ForceRendererGLTest.cpp | 2 +- .../DebugTools/Test/FrameProfilerTest.cpp | 3 +- .../DebugTools/Test/ObjectRendererGLTest.cpp | 2 +- src/Magnum/GL/Context.cpp | 4 +- src/Magnum/GL/DefaultFramebuffer.cpp | 2 +- src/Magnum/GL/Framebuffer.cpp | 2 +- src/Magnum/GL/Implementation/State.cpp | 28 +++++------ .../GL/Implementation/driverSpecific.cpp | 6 +-- src/Magnum/GL/Test/FramebufferGLTest.cpp | 50 +++++++++---------- src/Magnum/GL/Test/PixelStorageGLTest.cpp | 12 ++--- src/Magnum/Implementation/ImageProperties.h | 4 +- .../Math/Algorithms/Test/KahanSumTest.cpp | 6 +-- src/Magnum/Math/Tags.h | 2 - src/Magnum/MeshTools/Combine.cpp | 9 ++-- src/Magnum/MeshTools/CompressIndices.cpp | 2 +- src/Magnum/MeshTools/Concatenate.cpp | 4 +- src/Magnum/MeshTools/Concatenate.h | 4 +- src/Magnum/MeshTools/Duplicate.h | 2 +- src/Magnum/MeshTools/GenerateIndices.cpp | 24 ++++----- src/Magnum/MeshTools/GenerateNormals.cpp | 10 ++-- src/Magnum/MeshTools/Implementation/Tipsify.h | 4 +- src/Magnum/MeshTools/Interleave.cpp | 2 +- src/Magnum/MeshTools/Interleave.h | 2 +- src/Magnum/MeshTools/Reference.cpp | 4 +- src/Magnum/MeshTools/RemoveDuplicates.cpp | 16 +++--- src/Magnum/MeshTools/Subdivide.h | 4 +- src/Magnum/MeshTools/Test/ConcatenateTest.cpp | 4 +- .../Test/FullScreenTriangleGLTest.cpp | 4 +- .../MeshTools/Test/GenerateNormalsTest.cpp | 8 +-- src/Magnum/MeshTools/Test/InterleaveTest.cpp | 2 +- .../MeshTools/Test/RemoveDuplicatesTest.cpp | 2 +- src/Magnum/MeshTools/Test/SubdivideTest.cpp | 4 +- src/Magnum/MeshTools/Tipsify.cpp | 2 +- src/Magnum/MeshTools/sceneconverter.cpp | 2 +- src/Magnum/Platform/AbstractXApplication.cpp | 2 +- src/Magnum/Platform/AndroidApplication.cpp | 2 +- src/Magnum/Primitives/Circle.cpp | 2 +- src/Magnum/Primitives/Icosphere.cpp | 4 +- src/Magnum/Primitives/Plane.cpp | 2 +- src/Magnum/ShaderTools/AbstractConverter.cpp | 6 +-- src/Magnum/ShaderTools/shaderconverter.cpp | 8 +-- src/Magnum/Shaders/Phong.cpp | 10 ++-- src/Magnum/Shaders/Test/FlatGLTest.cpp | 4 +- src/Magnum/Shaders/Test/PhongGLTest.cpp | 20 ++++---- src/Magnum/Shaders/Test/VertexColorGLTest.cpp | 8 +-- src/Magnum/Tags.h | 18 +++++-- src/Magnum/Test/CMakeLists.txt | 5 +- src/Magnum/Test/ImageTest.cpp | 6 +-- src/Magnum/Test/ResourceManagerTest.cpp | 4 +- .../Text/Test/AbstractFontConverterTest.cpp | 8 +-- src/Magnum/Text/Test/RendererGLTest.cpp | 24 ++++----- .../Trade/Implementation/converterUtilities.h | 6 +-- src/Magnum/Trade/Test/AnimationDataTest.cpp | 6 +-- src/Magnum/Trade/Test/MaterialDataTest.cpp | 2 +- src/Magnum/Trade/Test/SkinDataTest.cpp | 4 +- src/Magnum/Vk/DescriptorPool.cpp | 2 +- src/Magnum/Vk/DescriptorSetLayout.cpp | 10 ++-- src/Magnum/Vk/Device.cpp | 4 +- src/Magnum/Vk/DeviceProperties.cpp | 8 +-- src/Magnum/Vk/Framebuffer.cpp | 4 +- .../Vk/Implementation/DriverWorkaround.cpp | 6 +-- src/Magnum/Vk/Implementation/spirvPatching.h | 4 +- src/Magnum/Vk/Instance.cpp | 4 +- src/Magnum/Vk/Mesh.cpp | 8 +-- src/Magnum/Vk/Pipeline.cpp | 6 +-- src/Magnum/Vk/PipelineLayout.cpp | 2 +- src/Magnum/Vk/Queue.cpp | 4 +- src/Magnum/Vk/RenderPass.cpp | 8 +-- src/Magnum/Vk/Shader.cpp | 2 +- src/Magnum/Vk/ShaderSet.cpp | 6 +-- src/Magnum/Vk/Test/PipelineTest.cpp | 6 +-- src/Magnum/Vk/Test/RenderPassTest.cpp | 2 +- .../AnyShaderConverter/AnyConverter.cpp | 2 +- .../Test/MagnumFontConverterTest.cpp | 2 +- src/MagnumPlugins/ObjImporter/ObjImporter.cpp | 4 +- .../TgaImageConverter/TgaImageConverter.cpp | 2 +- 85 files changed, 275 insertions(+), 272 deletions(-) diff --git a/doc/generated/colormaps.cpp b/doc/generated/colormaps.cpp index c811e620a..637655f69 100644 --- a/doc/generated/colormaps.cpp +++ b/doc/generated/colormaps.cpp @@ -56,7 +56,7 @@ int main() { constexpr Vector2i OutputSize{256, 12}; CORRADE_INTERNAL_ASSERT(image.first.size() == std::size_t(OutputSize.x())); - Containers::Array data{Containers::NoInit, std::size_t(OutputSize.product())}; + Containers::Array data{NoInit, std::size_t(OutputSize.product())}; Containers::StridedArrayView2D src{image.first, {std::size_t(OutputSize.y()), std::size_t(OutputSize.x())}, {0, 3}}; Containers::StridedArrayView2D dst{data, diff --git a/src/Magnum/Animation/Player.hpp b/src/Magnum/Animation/Player.hpp index 228ac600b..898bf802f 100644 --- a/src/Magnum/Animation/Player.hpp +++ b/src/Magnum/Animation/Player.hpp @@ -106,7 +106,7 @@ template Player& Player::addInternal(const TrackVi _duration = track.duration(); else _duration = Math::join(track.duration(), _duration); - arrayAppend(_tracks, Containers::InPlaceInit, track, advancer, destination, userCallback, userCallbackData, 0u); + arrayAppend(_tracks, InPlaceInit, track, advancer, destination, userCallback, userCallbackData, 0u); return *this; } @@ -252,7 +252,7 @@ template Containers::Optional> playe } } - return {Containers::InPlaceInit, playIteration, key}; + return {InPlaceInit, playIteration, key}; } } diff --git a/src/Magnum/Animation/Test/Benchmark.cpp b/src/Magnum/Animation/Test/Benchmark.cpp index b06460d64..13b7e02a8 100644 --- a/src/Magnum/Animation/Test/Benchmark.cpp +++ b/src/Magnum/Animation/Test/Benchmark.cpp @@ -83,8 +83,8 @@ Benchmark::Benchmark() { &Benchmark::playerAdvanceRawCallbackDirectInterpolator}, 10); _keys = Containers::Array{DataSize}; - _values = Containers::Array{Containers::DirectInit, DataSize, 1}; - _interleaved = Containers::Array>{Containers::DirectInit, DataSize, 0.0f, 1}; + _values = Containers::Array{DirectInit, DataSize, 1}; + _interleaved = Containers::Array>{DirectInit, DataSize, 0.0f, 1}; for(std::size_t i = 0; i != DataSize; ++i) _keys[i] = _interleaved[i].first = Float(i)*3.1254f; diff --git a/src/Magnum/Animation/Test/TrackTest.cpp b/src/Magnum/Animation/Test/TrackTest.cpp index 7a9dc88bc..5b1bc79d6 100644 --- a/src/Magnum/Animation/Test/TrackTest.cpp +++ b/src/Magnum/Animation/Test/TrackTest.cpp @@ -132,7 +132,7 @@ void TrackTest::constructEmpty() { void TrackTest::constructArrayInterpolator() { Track a{ - Containers::Array>{Containers::InPlaceInit, + Containers::Array>{InPlaceInit, {{1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}}, Math::select, Extrapolation::Extrapolated, Extrapolation::Constant}; @@ -162,7 +162,7 @@ void TrackTest::constructArrayInterpolator() { void TrackTest::constructArrayInterpolatorDefaults() { const Track a{ - Containers::Array>{Containers::InPlaceInit, + Containers::Array>{InPlaceInit, {{1.0f, {3.0f, 1.0f, 0.1f}}}}, Math::lerp, Extrapolation::DefaultConstructed}; @@ -183,7 +183,7 @@ void TrackTest::constructArrayInterpolatorDefaults() { void TrackTest::constructArrayInterpolation() { const Track a{ - Containers::Array>{Containers::InPlaceInit, + Containers::Array>{InPlaceInit, {{1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}}, Interpolation::Linear, Extrapolation::Extrapolated, Extrapolation::Constant}; @@ -205,7 +205,7 @@ void TrackTest::constructArrayInterpolation() { void TrackTest::constructArrayInterpolationDefaults() { const Track a{ - Containers::Array>{Containers::InPlaceInit, + Containers::Array>{InPlaceInit, {{1.0f, {3.0f, 1.0f, 0.1f}}}}, Interpolation::Constant, Extrapolation::DefaultConstructed}; @@ -228,7 +228,7 @@ Vector3 customLerp(const Vector3&, const Vector3&, Float) { return {}; } void TrackTest::constructArrayInterpolationInterpolator() { const Track a{ - Containers::Array>{Containers::InPlaceInit, + Containers::Array>{InPlaceInit, {{1.0f, {3.0f, 1.0f, 0.1f}}, {5.0f, {0.3f, 0.6f, 1.0f}}}}, Interpolation::Linear, customLerp, Extrapolation::Extrapolated, Extrapolation::Constant}; @@ -250,7 +250,7 @@ void TrackTest::constructArrayInterpolationInterpolator() { void TrackTest::constructArrayInterpolationInterpolationDefaults() { const Track a{ - Containers::Array>{Containers::InPlaceInit, + Containers::Array>{InPlaceInit, {{1.0f, {3.0f, 1.0f, 0.1f}}}}, Interpolation::Constant, customLerp, Extrapolation::DefaultConstructed}; diff --git a/src/Magnum/Animation/Track.h b/src/Magnum/Animation/Track.h index d31466a86..25b1ed463 100644 --- a/src/Magnum/Animation/Track.h +++ b/src/Magnum/Animation/Track.h @@ -164,7 +164,7 @@ template>&& data, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolator}, _interpolation{Interpolation::Custom}, _before{before}, _after{after} {} /** @overload */ - explicit Track(std::initializer_list> data, Interpolator interpolator, Extrapolation before, Extrapolation after): Track{Containers::Array>{Containers::InPlaceInit, data}, interpolator, before, after} {} + explicit Track(std::initializer_list> data, Interpolator interpolator, Extrapolation before, Extrapolation after): Track{Containers::Array>{InPlaceInit, data}, interpolator, before, after} {} /** @overload * Equivalent to calling @ref Track(Containers::Array>&&, Interpolator, Extrapolation, Extrapolation) @@ -173,7 +173,7 @@ template>&& data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track{std::move(data), interpolator, extrapolation, extrapolation} {} /** @overload */ - explicit Track(std::initializer_list> data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track{Containers::Array>{Containers::InPlaceInit, data}, interpolator, extrapolation, extrapolation} {} + explicit Track(std::initializer_list> data, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track{Containers::Array>{InPlaceInit, data}, interpolator, extrapolation, extrapolation} {} /** * @brief Construct with both generic and custom interpolator @@ -192,7 +192,7 @@ template>&& data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolator}, _interpolation{interpolation}, _before{before}, _after{after} {} /** @overload */ - explicit Track(std::initializer_list> data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after): Track{Containers::Array>{Containers::InPlaceInit, data}, interpolation, interpolator, before, after} {} + explicit Track(std::initializer_list> data, Interpolation interpolation, Interpolator interpolator, Extrapolation before, Extrapolation after): Track{Containers::Array>{InPlaceInit, data}, interpolation, interpolator, before, after} {} /** @overload * Equivalent to calling @ref Track(Containers::Array>&&, Interpolation, Interpolator, Extrapolation, Extrapolation) @@ -201,7 +201,7 @@ template>&& data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track{std::move(data), interpolation, interpolator, extrapolation, extrapolation} {} /** @overload */ - explicit Track(std::initializer_list> data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track{Containers::Array>{Containers::InPlaceInit, data}, interpolation, interpolator, extrapolation} {} + explicit Track(std::initializer_list> data, Interpolation interpolation, Interpolator interpolator, Extrapolation extrapolation = Extrapolation::Constant): Track{Containers::Array>{InPlaceInit, data}, interpolation, interpolator, extrapolation} {} /** * @brief Construct with generic interpolation behavior @@ -219,7 +219,7 @@ template>&& data, Interpolation interpolation, Extrapolation before, Extrapolation after) noexcept: _data{std::move(data)}, _interpolator{interpolatorFor(interpolation)}, _interpolation{interpolation}, _before{before}, _after{after} {} /** @overload */ - explicit Track(std::initializer_list> data, Interpolation interpolation, Extrapolation before, Extrapolation after): Track{Containers::Array>{Containers::InPlaceInit, data}, interpolation, before, after} {} + explicit Track(std::initializer_list> data, Interpolation interpolation, Extrapolation before, Extrapolation after): Track{Containers::Array>{InPlaceInit, data}, interpolation, before, after} {} /** @overload * Equivalent to calling @ref Track(Containers::Array>&&, Interpolation, Extrapolation, Extrapolation) @@ -228,7 +228,7 @@ template>&& data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant) noexcept: Track{std::move(data), interpolation, extrapolation, extrapolation} {} /** @overload */ - explicit Track(std::initializer_list> data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant): Track{Containers::Array>{Containers::InPlaceInit, data}, interpolation, extrapolation, extrapolation} {} + explicit Track(std::initializer_list> data, Interpolation interpolation, Extrapolation extrapolation = Extrapolation::Constant): Track{Containers::Array>{InPlaceInit, data}, interpolation, extrapolation, extrapolation} {} /** @brief Copying is not allowed */ Track(const Track&) = delete; diff --git a/src/Magnum/Audio/Test/AbstractImporterTest.cpp b/src/Magnum/Audio/Test/AbstractImporterTest.cpp index 28f6c3fe7..5a0453b1a 100644 --- a/src/Magnum/Audio/Test/AbstractImporterTest.cpp +++ b/src/Magnum/Audio/Test/AbstractImporterTest.cpp @@ -340,7 +340,7 @@ void AbstractImporterTest::data() { } } importer; - CORRADE_COMPARE_AS(importer.data(), (Containers::Array{Containers::InPlaceInit, {'H'}}), TestSuite::Compare::Container); + CORRADE_COMPARE_AS(importer.data(), (Containers::Array{InPlaceInit, {'H'}}), TestSuite::Compare::Container); } void AbstractImporterTest::dataNoFile() { diff --git a/src/Magnum/DebugTools/CompareImage.cpp b/src/Magnum/DebugTools/CompareImage.cpp index 2b9f4db6d..57f83db10 100644 --- a/src/Magnum/DebugTools/CompareImage.cpp +++ b/src/Magnum/DebugTools/CompareImage.cpp @@ -95,7 +95,7 @@ template Float calculateImageDelta(const Containers:: std::tuple, Float, Float> calculateImageDelta(const PixelFormat actualFormat, const Containers::StridedArrayView3D& actualPixels, const ImageView2D& expected) { /* Calculate a delta image */ - Containers::Array deltaData{Containers::NoInit, + Containers::Array deltaData{NoInit, std::size_t(expected.size().product())}; Containers::StridedArrayView2D delta{deltaData, {std::size_t(expected.size().y()), std::size_t(expected.size().x())}}; @@ -446,7 +446,7 @@ class ImageComparatorBase::State { Containers::Array delta; }; -ImageComparatorBase::ImageComparatorBase(PluginManager::Manager* importerManager, PluginManager::Manager* converterManager, Float maxThreshold, Float meanThreshold): _state{Containers::InPlaceInit, importerManager, converterManager, maxThreshold, meanThreshold} { +ImageComparatorBase::ImageComparatorBase(PluginManager::Manager* importerManager, PluginManager::Manager* converterManager, Float maxThreshold, Float meanThreshold): _state{InPlaceInit, importerManager, converterManager, maxThreshold, meanThreshold} { CORRADE_ASSERT(!Math::isNan(maxThreshold) && !Math::isInf(maxThreshold) && !Math::isNan(meanThreshold) && !Math::isInf(meanThreshold), "DebugTools::CompareImage: thresholds can't be NaN or infinity", ); diff --git a/src/Magnum/DebugTools/FrameProfiler.cpp b/src/Magnum/DebugTools/FrameProfiler.cpp index f2f32f2a9..95aacdf12 100644 --- a/src/Magnum/DebugTools/FrameProfiler.cpp +++ b/src/Magnum/DebugTools/FrameProfiler.cpp @@ -181,7 +181,7 @@ void FrameProfiler::endFrame() { /* If we don't have all frames yet, enlarge the array */ if(++_measuredFrameCount <= _maxFrameCount) - arrayAppend(_data, Containers::NoInit, _measurements.size()); + arrayAppend(_data, NoInit, _measurements.size()); /* Wrap up measurements for this frame */ for(std::size_t i = 0; i != _measurements.size(); ++i) { @@ -448,7 +448,7 @@ struct GLFrameProfiler::State { #endif }; -GLFrameProfiler::GLFrameProfiler(): _state{Containers::InPlaceInit} {} +GLFrameProfiler::GLFrameProfiler(): _state{InPlaceInit} {} GLFrameProfiler::GLFrameProfiler(const Values values, const UnsignedInt maxFrameCount): GLFrameProfiler{} { @@ -468,7 +468,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount /* Fucking hell, STL. When I first saw std::chrono back in 2010 I should have flipped the table and learn carpentry instead. BUT NO, I'm still suffering this abomination a decade later! */ - arrayAppend(measurements, Containers::InPlaceInit, + arrayAppend(measurements, InPlaceInit, "Frame time", Units::Nanoseconds, UnsignedInt(Containers::arraySize(_state->frameTimeStartFrame)), [](void* state, UnsignedInt current) { static_cast(state)->frameTimeStartFrame[current] = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); @@ -482,7 +482,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount _state->frameTimeIndex = index++; } if(values & Value::CpuDuration) { - arrayAppend(measurements, Containers::InPlaceInit, + arrayAppend(measurements, InPlaceInit, "CPU duration", Units::Nanoseconds, [](void* state) { static_cast(state)->cpuDurationStartFrame = std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); @@ -496,7 +496,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount if(values & Value::GpuDuration) { for(GL::TimeQuery& q: _state->timeQueries) q = GL::TimeQuery{GL::TimeQuery::Target::TimeElapsed}; - arrayAppend(measurements, Containers::InPlaceInit, + arrayAppend(measurements, InPlaceInit, "GPU duration", Units::Nanoseconds, UnsignedInt(Containers::arraySize(_state->timeQueries)), [](void* state, UnsignedInt current) { @@ -516,7 +516,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VerticesSubmitted}; for(GL::PipelineStatisticsQuery& q: _state->vertexShaderInvocationsQueries) q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::VertexShaderInvocations}; - arrayAppend(measurements, Containers::InPlaceInit, + arrayAppend(measurements, InPlaceInit, "Vertex fetch ratio", Units::RatioThousandths, UnsignedInt(Containers::arraySize(_state->verticesSubmittedQueries)), [](void* state, UnsignedInt current) { @@ -541,7 +541,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingInputPrimitives}; for(GL::PipelineStatisticsQuery& q: _state->clippingOutputPrimitivesQueries) q = GL::PipelineStatisticsQuery{GL::PipelineStatisticsQuery::Target::ClippingOutputPrimitives}; - arrayAppend(measurements, Containers::InPlaceInit, + arrayAppend(measurements, InPlaceInit, "Primitives clipped", Units::PercentageThousandths, UnsignedInt(Containers::arraySize(_state->clippingInputPrimitivesQueries)), [](void* state, UnsignedInt current) { diff --git a/src/Magnum/DebugTools/Test/CompareImageTest.cpp b/src/Magnum/DebugTools/Test/CompareImageTest.cpp index 82600d78c..ad63602c6 100644 --- a/src/Magnum/DebugTools/Test/CompareImageTest.cpp +++ b/src/Magnum/DebugTools/Test/CompareImageTest.cpp @@ -317,10 +317,10 @@ void CompareImageTest::calculateDeltaStorage() { Float max, mean; std::tie(delta, max, mean) = Implementation::calculateImageDelta(ActualRgb.format(), ActualRgb.pixels(), ExpectedRgb); - CORRADE_COMPARE_AS(delta, (Containers::Array{Containers::InPlaceInit, { + CORRADE_COMPARE_AS(delta, Containers::arrayView({ 1.0f/3.0f, (55.0f + 1.0f)/3.0f, 48.0f/3.0f, 117.0f/3.0f - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); CORRADE_COMPARE(max, 117.0f/3.0f); CORRADE_COMPARE(mean, 18.5f); } @@ -381,9 +381,9 @@ void CompareImageTest::calculateDeltaSpecials3() { Containers::Array delta; Float max, mean; std::tie(delta, max, mean) = Implementation::calculateImageDelta(actualSpecials3.format(), actualSpecials3.pixels(), expectedSpecials3); - CORRADE_COMPARE_AS(delta, (Containers::Array{Containers::InPlaceInit, { + CORRADE_COMPARE_AS(delta, Containers::arrayView({ Constants::nan(), Constants::nan(), 1.15f - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); /* Max and mean should be calculated *without* the specials because otherwise every other potential difference will be zero compared to infinity */ diff --git a/src/Magnum/DebugTools/Test/ForceRendererGLTest.cpp b/src/Magnum/DebugTools/Test/ForceRendererGLTest.cpp index c2d9ad56c..524c58960 100644 --- a/src/Magnum/DebugTools/Test/ForceRendererGLTest.cpp +++ b/src/Magnum/DebugTools/Test/ForceRendererGLTest.cpp @@ -117,7 +117,7 @@ void ForceRendererGLTest::render2D() { the arrowhead to be on a different place (but the rest is okay and the 3D case matches exactly), however to avoid false negatives elsewhere I'm making it conditional. */ - Containers::Optional comparator{Containers::InPlaceInit, _manager}; + Containers::Optional comparator{InPlaceInit, _manager}; #ifdef CORRADE_TARGET_ANDROID if(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali) comparator.emplace(_manager, 79.0f, 0.22f); diff --git a/src/Magnum/DebugTools/Test/FrameProfilerTest.cpp b/src/Magnum/DebugTools/Test/FrameProfilerTest.cpp index 1d65f718e..16a65fc83 100644 --- a/src/Magnum/DebugTools/Test/FrameProfilerTest.cpp +++ b/src/Magnum/DebugTools/Test/FrameProfilerTest.cpp @@ -1114,8 +1114,7 @@ void FrameProfilerTest::gl() { setTestCaseDescription(data.name); /* Test that we use the right state pointers to survive a move */ - Containers::Pointer profiler_{Containers::InPlaceInit, - data.values, 4u}; + Containers::Pointer profiler_{InPlaceInit, data.values, 4u}; GLFrameProfiler profiler = std::move(*profiler_); profiler_ = nullptr; CORRADE_COMPARE(profiler.values(), data.values); diff --git a/src/Magnum/DebugTools/Test/ObjectRendererGLTest.cpp b/src/Magnum/DebugTools/Test/ObjectRendererGLTest.cpp index 9b0b82d15..d7ee1b490 100644 --- a/src/Magnum/DebugTools/Test/ObjectRendererGLTest.cpp +++ b/src/Magnum/DebugTools/Test/ObjectRendererGLTest.cpp @@ -164,7 +164,7 @@ void ObjectRendererGLTest::render3D() { the bottom blue line to be on a different place (but the rest is okay and the 2D case matches exactly), however to avoid false negatives elsewhere I'm making it conditional. */ - Containers::Optional comparator{Containers::InPlaceInit, _manager, 71.6f, 0.018f}; + Containers::Optional comparator{InPlaceInit, _manager, 71.6f, 0.018f}; #ifdef CORRADE_TARGET_ANDROID if(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::ArmMali) comparator.emplace(_manager, 127.6f, 0.54f); diff --git a/src/Magnum/GL/Context.cpp b/src/Magnum/GL/Context.cpp index 8d04b9a7d..53d9463bf 100644 --- a/src/Magnum/GL/Context.cpp +++ b/src/Magnum/GL/Context.cpp @@ -796,7 +796,7 @@ bool Context::tryCreate(const Configuration& configuration) { /* Driver workarounds get merged. Not using disableDriverWorkaround() here since the Configuration already contains the internal string views. */ for(const Containers::StringView workaround: configuration.disabledWorkarounds()) - arrayAppend(_driverWorkarounds, Containers::InPlaceInit, workaround, true); + arrayAppend(_driverWorkarounds, InPlaceInit, workaround, true); /* Extensions get merged also. Here we had the chance to force users to give us the predefined extension types so no need to search for their @@ -1208,7 +1208,7 @@ Context::Configuration& Context::Configuration::operator=(const Configuration& o _flags = other._flags; arrayResize(_disabledWorkarounds, 0); /** @todo arrayClear(), ffs */ - arrayResize(_disabledExtensions, Containers::NoInit, 0); + arrayResize(_disabledExtensions, NoInit, 0); addDisabledWorkarounds(other._disabledWorkarounds); addDisabledExtensions(other._disabledExtensions); return *this; diff --git a/src/Magnum/GL/DefaultFramebuffer.cpp b/src/Magnum/GL/DefaultFramebuffer.cpp index b86c3b852..8c2bb1642 100644 --- a/src/Magnum/GL/DefaultFramebuffer.cpp +++ b/src/Magnum/GL/DefaultFramebuffer.cpp @@ -69,7 +69,7 @@ DefaultFramebuffer& DefaultFramebuffer::mapForDraw(std::initializer_list _attachments{Containers::ValueInit, max+1}; + Containers::Array _attachments{ValueInit, max+1}; for(const auto& attachment: attachments) _attachments[attachment.first] = GLenum(attachment.second); diff --git a/src/Magnum/GL/Framebuffer.cpp b/src/Magnum/GL/Framebuffer.cpp index e1edba78a..eef4bd57b 100644 --- a/src/Magnum/GL/Framebuffer.cpp +++ b/src/Magnum/GL/Framebuffer.cpp @@ -185,7 +185,7 @@ Framebuffer& Framebuffer::mapForDraw(std::initializer_list _attachments{Containers::ValueInit, max+1}; + Containers::Array _attachments{ValueInit, max+1}; for(const auto& attachment: attachments) _attachments[attachment.first] = GLenum(attachment.second); diff --git a/src/Magnum/GL/Implementation/State.cpp b/src/Magnum/GL/Implementation/State.cpp index 03225464e..582bf6ef7 100644 --- a/src/Magnum/GL/Implementation/State.cpp +++ b/src/Magnum/GL/Implementation/State.cpp @@ -92,25 +92,25 @@ std::pair State::allocate(Context& context, std: Containers::ArrayView transformFeedbackStateView; #endif Containers::ArrayTuple data{ - {Containers::NoInit, 1, stateView}, - {Containers::NoInit, 1, bufferStateView}, - {Containers::NoInit, 1, contextStateView}, + {NoInit, 1, stateView}, + {NoInit, 1, bufferStateView}, + {NoInit, 1, contextStateView}, #ifndef MAGNUM_TARGET_WEBGL - {Containers::NoInit, 1, debugStateView}, + {NoInit, 1, debugStateView}, #endif - {Containers::NoInit, 1, framebufferStateView}, - {Containers::NoInit, 1, meshStateView}, - {Containers::NoInit, 1, queryStateView}, - {Containers::NoInit, 1, rendererStateView}, - {Containers::NoInit, 1, shaderStateView}, - {Containers::NoInit, 1, shaderProgramStateView}, - {Containers::NoInit, 1, textureStateView}, - {Containers::ValueInit, std::size_t(maxTextureUnits), textureBindings}, + {NoInit, 1, framebufferStateView}, + {NoInit, 1, meshStateView}, + {NoInit, 1, queryStateView}, + {NoInit, 1, rendererStateView}, + {NoInit, 1, shaderStateView}, + {NoInit, 1, shaderProgramStateView}, + {NoInit, 1, textureStateView}, + {ValueInit, std::size_t(maxTextureUnits), textureBindings}, #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - {Containers::ValueInit, std::size_t(maxImageUnits), imageBindings}, + {ValueInit, std::size_t(maxImageUnits), imageBindings}, #endif #ifndef MAGNUM_TARGET_GLES2 - {Containers::NoInit, 1, transformFeedbackStateView} + {NoInit, 1, transformFeedbackStateView} #endif }; diff --git a/src/Magnum/GL/Implementation/driverSpecific.cpp b/src/Magnum/GL/Implementation/driverSpecific.cpp index 9ac84a136..6f999a175 100644 --- a/src/Magnum/GL/Implementation/driverSpecific.cpp +++ b/src/Magnum/GL/Implementation/driverSpecific.cpp @@ -496,7 +496,7 @@ void Context::disableDriverWorkaround(const Containers::StringView workaround) { return; } - arrayAppend(_driverWorkarounds, Containers::InPlaceInit, found, true); + arrayAppend(_driverWorkarounds, InPlaceInit, found, true); } bool Context::isDriverWorkaroundDisabled(const Containers::StringView workaround) { @@ -512,7 +512,7 @@ bool Context::isDriverWorkaroundDisabled(const Containers::StringView workaround the views in the KnownWorkarounds list. */ for(const auto& i: _driverWorkarounds) if(i.first.data() == found.data()) return i.second; - arrayAppend(_driverWorkarounds, Containers::InPlaceInit, found, false); + arrayAppend(_driverWorkarounds, InPlaceInit, found, false); return false; } @@ -633,7 +633,7 @@ Context::Configuration& Context::Configuration::addDisabledWorkarounds(Container continue; } - arrayAppend(_disabledWorkarounds, Containers::InPlaceInit, found); + arrayAppend(_disabledWorkarounds, InPlaceInit, found); } return *this; diff --git a/src/Magnum/GL/Test/FramebufferGLTest.cpp b/src/Magnum/GL/Test/FramebufferGLTest.cpp index d4dfddb58..1fed5ef74 100644 --- a/src/Magnum/GL/Test/FramebufferGLTest.cpp +++ b/src/Magnum/GL/Test/FramebufferGLTest.cpp @@ -1728,7 +1728,7 @@ void FramebufferGLTest::copyImageTexture1D() { CORRADE_COMPARE(texture.imageSize(0)[0], 2); CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, {0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b}}), + Containers::arrayView({0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b}), TestSuite::Compare::Container); } #endif @@ -1770,9 +1770,9 @@ void FramebufferGLTest::copyImageTexture2D() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(texture.imageSize(0), Vector2i{2}); CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b}}), + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b}), TestSuite::Compare::Container); #endif } @@ -1798,9 +1798,9 @@ void FramebufferGLTest::copyImageTexture1DArray() { CORRADE_COMPARE(texture.imageSize(0), Vector2i{2}); CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b}}), + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b}), TestSuite::Compare::Container); } @@ -1824,9 +1824,9 @@ void FramebufferGLTest::copyImageRectangleTexture() { CORRADE_COMPARE(texture.imageSize(), Vector2i{2}); CORRADE_COMPARE_AS(texture.image({PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b}}), + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b}), TestSuite::Compare::Container); } #endif @@ -1875,9 +1875,9 @@ void FramebufferGLTest::copyImageCubeMapTexture() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE(texture.imageSize(0), Vector2i{2}); CORRADE_COMPARE_AS(texture.image(CubeMapCoordinate::PositiveX, 0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b}}), + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b}), TestSuite::Compare::Container); #endif } @@ -1902,8 +1902,8 @@ void FramebufferGLTest::copySubImageTexture1D() { MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { - 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00}}), + Containers::arrayView({ + 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00}), TestSuite::Compare::Container); } #endif @@ -1946,11 +1946,11 @@ void FramebufferGLTest::copySubImageTexture2D() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), TestSuite::Compare::Container); #endif } @@ -1993,7 +1993,7 @@ void FramebufferGLTest::copySubImageTexture3D() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -2002,7 +2002,7 @@ void FramebufferGLTest::copySubImageTexture3D() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), TestSuite::Compare::Container); #endif } @@ -2030,11 +2030,11 @@ void FramebufferGLTest::copySubImageTexture1DArray() { MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), TestSuite::Compare::Container); } #endif @@ -2064,7 +2064,7 @@ void FramebufferGLTest::copySubImageTexture2DArray() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -2073,7 +2073,7 @@ void FramebufferGLTest::copySubImageTexture2DArray() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), TestSuite::Compare::Container); #endif } @@ -2101,11 +2101,11 @@ void FramebufferGLTest::copySubImageRectangleTexture() { MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE_AS(texture.image({PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), TestSuite::Compare::Container); } #endif @@ -2148,11 +2148,11 @@ void FramebufferGLTest::copySubImageCubeMapTexture() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE_AS(texture.image(CubeMapCoordinate::NegativeY, 0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), TestSuite::Compare::Container); #endif } @@ -2185,7 +2185,7 @@ void FramebufferGLTest::copySubImageCubeMapTextureArray() { #ifndef MAGNUM_TARGET_GLES CORRADE_COMPARE_AS(texture.image(0, {PixelFormat::RGBA, PixelType::UnsignedByte}).release(), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -2214,7 +2214,7 @@ void FramebufferGLTest::copySubImageCubeMapTextureArray() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}), + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}), TestSuite::Compare::Container); #endif } diff --git a/src/Magnum/GL/Test/PixelStorageGLTest.cpp b/src/Magnum/GL/Test/PixelStorageGLTest.cpp index 5bb4d1809..7e163e3c2 100644 --- a/src/Magnum/GL/Test/PixelStorageGLTest.cpp +++ b/src/Magnum/GL/Test/PixelStorageGLTest.cpp @@ -120,7 +120,7 @@ void PixelStorageGLTest::unpack2D() { /* Read into zero-initialized array to avoid comparing random memory in padding bytes (confirmed on NVidia 355.11, AMD 15.300.1025.0) */ Image2D actual{PixelFormat::RGB, PixelType::UnsignedByte, {}, - Containers::Array{Containers::ValueInit, sizeof(ActualData)}}; + Containers::Array{ValueInit, sizeof(ActualData)}}; #ifndef MAGNUM_TARGET_GLES texture.image(0, actual); @@ -158,7 +158,7 @@ void PixelStorageGLTest::pack2D() { .setAlignment(2) .setRowLength(3) .setSkip({1, 3, 0}), - PixelFormat::RGB, PixelType::UnsignedByte, {}, Containers::Array{Containers::ValueInit, sizeof(Data2D)}}; + PixelFormat::RGB, PixelType::UnsignedByte, {}, Containers::Array{ValueInit, sizeof(Data2D)}}; #ifndef MAGNUM_TARGET_GLES texture.image(0, image); @@ -218,7 +218,7 @@ void PixelStorageGLTest::unpack3D() { /* Read into zero-initialized array to avoid comparing random memory in padding bytes (confirmed on AMD 15.300.1025.0) */ Image3D actual{PixelFormat::RGB, PixelType::UnsignedByte, {}, - Containers::Array{Containers::ValueInit, sizeof(ActualData)}}; + Containers::Array{ValueInit, sizeof(ActualData)}}; texture.image(0, actual); @@ -252,7 +252,7 @@ void PixelStorageGLTest::pack3D() { .setRowLength(3) .setImageHeight(5) .setSkip({1, 2, 1}), - PixelFormat::RGB, PixelType::UnsignedByte, {}, Containers::Array{Containers::ValueInit, sizeof(Data3D)}}; + PixelFormat::RGB, PixelType::UnsignedByte, {}, Containers::Array{ValueInit, sizeof(Data3D)}}; texture.image(0, image); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -330,7 +330,7 @@ void PixelStorageGLTest::packCompressed2D() { .setCompressedBlockDataSize(16) .setRowLength(12) .setSkip({4, 4, 0}), - CompressedPixelFormat::RGBAS3tcDxt3, {}, Containers::Array{Containers::ValueInit, sizeof(CompressedData2D)}}; + CompressedPixelFormat::RGBAS3tcDxt3, {}, Containers::Array{ValueInit, sizeof(CompressedData2D)}}; texture.compressedImage(0, image); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -438,7 +438,7 @@ void PixelStorageGLTest::packCompressed3D() { .setRowLength(8) .setImageHeight(8) .setSkip({4, 4, 4}), - CompressedPixelFormat::RGBAS3tcDxt3, {}, Containers::Array{Containers::ValueInit, sizeof(CompressedData3D)}}; + CompressedPixelFormat::RGBAS3tcDxt3, {}, Containers::Array{ValueInit, sizeof(CompressedData3D)}}; texture.compressedImage(0, image); MAGNUM_VERIFY_NO_GL_ERROR(); diff --git a/src/Magnum/Implementation/ImageProperties.h b/src/Magnum/Implementation/ImageProperties.h index 3e164a14e..c94068afc 100644 --- a/src/Magnum/Implementation/ImageProperties.h +++ b/src/Magnum/Implementation/ImageProperties.h @@ -51,7 +51,7 @@ template Containers::S /* Size in the last dimension is byte size of the pixel, the remaining dimensions are reverted (first images, then rows, then pixels, last pixel bytes) */ - Containers::StridedDimensions size{Containers::NoInit}; + Containers::StridedDimensions size{NoInit}; size[dimensions] = image.pixelSize(); for(UnsignedInt i = dimensions; i != 0; --i) size[i - 1] = image.size()[dimensions - i]; @@ -61,7 +61,7 @@ template Containers::S (first image size, then row size, then pixel size, last 1). The data properties include pixel size in row size, so we have to take it out from the cumulative product. */ - Containers::StridedDimensions stride{Containers::NoInit}; + Containers::StridedDimensions stride{NoInit}; stride[dimensions] = 1; stride[dimensions - 1] = 1; for(UnsignedInt i = dimensions - 1; i != 0; --i) diff --git a/src/Magnum/Math/Algorithms/Test/KahanSumTest.cpp b/src/Magnum/Math/Algorithms/Test/KahanSumTest.cpp index 3ff7e0024..6095290d9 100644 --- a/src/Magnum/Math/Algorithms/Test/KahanSumTest.cpp +++ b/src/Magnum/Math/Algorithms/Test/KahanSumTest.cpp @@ -143,7 +143,7 @@ void KahanSumTest::iterative() { } void KahanSumTest::accumulate100kFloats() { - Containers::Array data(Containers::DirectInit, 100000, 1.0f); + Containers::Array data(DirectInit, 100000, 1.0f); volatile Float a; /* to avoid optimizing the loop out */ CORRADE_BENCHMARK(10) { @@ -154,7 +154,7 @@ void KahanSumTest::accumulate100kFloats() { } void KahanSumTest::accumulate100kDoubles() { - Containers::Array data(Containers::DirectInit, 100000, 1.0); + Containers::Array data(DirectInit, 100000, 1.0); volatile Double a; /* to avoid optimizing the loop out */ CORRADE_BENCHMARK(10) { @@ -165,7 +165,7 @@ void KahanSumTest::accumulate100kDoubles() { } void KahanSumTest::kahan100kFloats() { - Containers::Array data(Containers::DirectInit, 100000, 1.0f); + Containers::Array data(DirectInit, 100000, 1.0f); volatile Float a; /* to avoid optimizing the loop out */ CORRADE_BENCHMARK(10) { diff --git a/src/Magnum/Math/Tags.h b/src/Magnum/Math/Tags.h index 0e655bbb1..f130ed6f2 100644 --- a/src/Magnum/Math/Tags.h +++ b/src/Magnum/Math/Tags.h @@ -29,8 +29,6 @@ * @brief Tag type @ref Magnum::Math::ZeroInitT, @ref Magnum::Math::IdentityInitT, tag @ref Magnum::Math::ZeroInit, @ref Magnum::Math::IdentityInit */ -#include - #include "Magnum/Tags.h" #ifdef MAGNUM_BUILD_DEPRECATED diff --git a/src/Magnum/MeshTools/Combine.cpp b/src/Magnum/MeshTools/Combine.cpp index 5e567374f..7f0792e5e 100644 --- a/src/Magnum/MeshTools/Combine.cpp +++ b/src/Magnum/MeshTools/Combine.cpp @@ -59,8 +59,7 @@ Trade::MeshData combineIndexedImplementation(const MeshPrimitive primitive, Cont /* Allocate resulting attribute and vertex data and duplicate the attributes there according to the combined index buffer */ - Containers::Array vertexData{Containers::NoInit, - vertexStride*vertexCount}; + Containers::Array vertexData{NoInit, vertexStride*vertexCount}; Containers::Array attributeData{attributeCount}; { std::size_t indexOffset = 0; @@ -133,8 +132,7 @@ Trade::MeshData combineIndexedAttributes(const Containers::ArrayView combinedIndices{Containers::NoInit, - indexCount*indexStride}; + Containers::Array combinedIndices{NoInit, indexCount*indexStride}; { std::size_t indexOffset = 0; for(const Trade::MeshData& mesh: data) { @@ -177,8 +175,7 @@ Trade::MeshData combineFaceAttributes(const Trade::MeshData& mesh, const Trade:: const UnsignedInt faceIndexSize = faceAttributes.isIndexed() ? meshIndexTypeSize(faceAttributes.indexType()) : 4; const UnsignedInt indexStride = meshIndexSize + faceIndexSize; - Containers::Array combinedIndices{Containers::NoInit, - meshIndexCount*indexStride}; + Containers::Array combinedIndices{NoInit, meshIndexCount*indexStride}; Utility::copy(mesh.indices(), Containers::StridedArrayView2D{combinedIndices, {meshIndexCount, meshIndexSize}, {std::ptrdiff_t(indexStride), 1}}); diff --git a/src/Magnum/MeshTools/CompressIndices.cpp b/src/Magnum/MeshTools/CompressIndices.cpp index 261e0d1e7..82f0b226a 100644 --- a/src/Magnum/MeshTools/CompressIndices.cpp +++ b/src/Magnum/MeshTools/CompressIndices.cpp @@ -127,7 +127,7 @@ Trade::MeshData compressIndices(Trade::MeshData&& data, MeshIndexType atLeast) { if(data.vertexDataFlags() & Trade::DataFlag::Owned) vertexData = data.releaseVertexData(); else { - vertexData = Containers::Array{Containers::NoInit, data.vertexData().size()}; + vertexData = Containers::Array{NoInit, data.vertexData().size()}; Utility::copy(data.vertexData(), vertexData); } diff --git a/src/Magnum/MeshTools/Concatenate.cpp b/src/Magnum/MeshTools/Concatenate.cpp index 16ade1747..f50596b5e 100644 --- a/src/Magnum/MeshTools/Concatenate.cpp +++ b/src/Magnum/MeshTools/Concatenate.cpp @@ -208,9 +208,9 @@ Trade::MeshData concatenate(const Containers::ArrayView indexVertexCount = Implementation::concatenateIndexVertexCount(meshes); - Containers::Array indexData{Containers::NoInit, + Containers::Array indexData{NoInit, indexVertexCount.first*sizeof(UnsignedInt)}; - Containers::Array vertexData{Containers::ValueInit, + Containers::Array vertexData{ValueInit, attributeData.empty() ? 0 : (attributeData[0].stride()*indexVertexCount.second)}; return Implementation::concatenate(std::move(indexData), indexVertexCount.second, std::move(vertexData), std::move(attributeData), meshes, "MeshTools::concatenate():"); } diff --git a/src/Magnum/MeshTools/Concatenate.h b/src/Magnum/MeshTools/Concatenate.h index 88db82de5..a2f9230c3 100644 --- a/src/Magnum/MeshTools/Concatenate.h +++ b/src/Magnum/MeshTools/Concatenate.h @@ -106,7 +106,7 @@ template class Allocator = Containers::ArrayAllocator> void conc indexData = destination.releaseIndexData(); /* Everything is overwritten here so we don't need to zero-out the memory */ - Containers::arrayResize(indexData, Containers::NoInit, indexVertexCount.first*sizeof(UnsignedInt)); + Containers::arrayResize(indexData, NoInit, indexVertexCount.first*sizeof(UnsignedInt)); } Containers::Array attributeData = Implementation::interleavedLayout(std::move(destination), {}); @@ -118,7 +118,7 @@ template class Allocator = Containers::ArrayAllocator> void conc there, otherwise attributes that are not present in `meshes` would be garbage */ Containers::arrayResize(vertexData, 0); - Containers::arrayResize(vertexData, Containers::ValueInit, attributeStride*indexVertexCount.second); + Containers::arrayResize(vertexData, ValueInit, attributeStride*indexVertexCount.second); } destination = Implementation::concatenate(std::move(indexData), indexVertexCount.second, std::move(vertexData), std::move(attributeData), meshes, "MeshTools::concatenateInto():"); diff --git a/src/Magnum/MeshTools/Duplicate.h b/src/Magnum/MeshTools/Duplicate.h index 7515babd5..bb537e3f5 100644 --- a/src/Magnum/MeshTools/Duplicate.h +++ b/src/Magnum/MeshTools/Duplicate.h @@ -62,7 +62,7 @@ use @ref duplicateInto(). @see @ref removeDuplicatesInPlace(), @ref combineIndexedAttributes() */ template Containers::Array duplicate(const Containers::StridedArrayView1D& indices, const Containers::StridedArrayView1D& data) { - Containers::Array out{Containers::NoInit, indices.size()}; + Containers::Array out{NoInit, indices.size()}; duplicateInto(indices, data, out); return out; } diff --git a/src/Magnum/MeshTools/GenerateIndices.cpp b/src/Magnum/MeshTools/GenerateIndices.cpp index c628c24f4..60a7cae65 100644 --- a/src/Magnum/MeshTools/GenerateIndices.cpp +++ b/src/Magnum/MeshTools/GenerateIndices.cpp @@ -76,7 +76,7 @@ void generateLineStripIndicesInto(const UnsignedInt vertexCount, const Container } Containers::Array generateLineStripIndices(const UnsignedInt vertexCount) { - Containers::Array indices{Containers::NoInit, 2*(vertexCount - 1)}; + Containers::Array indices{NoInit, 2*(vertexCount - 1)}; generateLineStripIndicesInto(vertexCount, indices); return indices; } @@ -105,7 +105,7 @@ void generateLineLoopIndicesInto(const UnsignedInt vertexCount, const Containers } Containers::Array generateLineLoopIndices(const UnsignedInt vertexCount) { - Containers::Array indices{Containers::NoInit, 2*vertexCount}; + Containers::Array indices{NoInit, 2*vertexCount}; generateLineLoopIndicesInto(vertexCount, indices); return indices; } @@ -134,7 +134,7 @@ void generateTriangleStripIndicesInto(const UnsignedInt vertexCount, const Conta } Containers::Array generateTriangleStripIndices(const UnsignedInt vertexCount) { - Containers::Array indices{Containers::NoInit, 3*(vertexCount - 2)}; + Containers::Array indices{NoInit, 3*(vertexCount - 2)}; generateTriangleStripIndicesInto(vertexCount, indices); return indices; } @@ -164,7 +164,7 @@ void generateTriangleFanIndicesInto(const UnsignedInt vertexCount, const Contain } Containers::Array generateTriangleFanIndices(const UnsignedInt vertexCount) { - Containers::Array indices{Containers::NoInit, 3*(vertexCount - 2)}; + Containers::Array indices{NoInit, 3*(vertexCount - 2)}; generateTriangleFanIndicesInto(vertexCount, indices); return indices; } @@ -216,14 +216,14 @@ template inline void generateQuadIndicesIntoImplementation(const Contai Containers::Array generateQuadIndices(const Containers::StridedArrayView1D& positions, const Containers::StridedArrayView1D& quads) { /* We can skip zero-initialization here */ - Containers::Array out{Containers::NoInit, quads.size()*6/4}; + Containers::Array out{NoInit, quads.size()*6/4}; generateQuadIndicesIntoImplementation(positions, quads, Containers::stridedArrayView(out)); return out; } Containers::Array generateQuadIndices(const Containers::StridedArrayView1D& positions, const Containers::StridedArrayView1D& quads) { /* Explicitly ensure we have the unused bytes zeroed out */ - Containers::Array out{Containers::ValueInit, quads.size()*6/4}; + Containers::Array out{ValueInit, quads.size()*6/4}; generateQuadIndicesIntoImplementation(positions, quads, /* Could be just arrayCast(stridedArrayView(out) on LE, but I want to be sure as much as possible that this compiles on BE @@ -241,7 +241,7 @@ Containers::Array generateQuadIndices(const Containers::StridedArra Containers::Array generateQuadIndices(const Containers::StridedArrayView1D& positions, const Containers::StridedArrayView1D& quads) { /* Explicitly ensure we have the unused bytes zeroed out */ - Containers::Array out{Containers::ValueInit, quads.size()*6/4}; + Containers::Array out{ValueInit, quads.size()*6/4}; generateQuadIndicesIntoImplementation(positions, quads, /* Could be just arrayCast(stridedArrayView(out) on LE, but I want to be sure as much as possible that this compiles on BE @@ -281,7 +281,7 @@ Trade::MeshData generateIndices(Trade::MeshData&& data) { if(data.vertexDataFlags() & Trade::DataFlag::Owned) vertexData = data.releaseVertexData(); else { - vertexData = Containers::Array{Containers::NoInit, data.vertexData().size()}; + vertexData = Containers::Array{NoInit, data.vertexData().size()}; Utility::copy(data.vertexData(), vertexData); } @@ -301,19 +301,19 @@ Trade::MeshData generateIndices(Trade::MeshData&& data) { Containers::Array indexData; if(data.primitive() == MeshPrimitive::LineStrip) { primitive = MeshPrimitive::Lines; - indexData = Containers::Array{Containers::NoInit, 2*(vertexCount - 1)*sizeof(UnsignedInt)}; + indexData = Containers::Array{NoInit, 2*(vertexCount - 1)*sizeof(UnsignedInt)}; generateLineStripIndicesInto(vertexCount, Containers::arrayCast(indexData)); } else if(data.primitive() == MeshPrimitive::LineLoop) { primitive = MeshPrimitive::Lines; - indexData = Containers::Array{Containers::NoInit, 2*vertexCount*sizeof(UnsignedInt)}; + indexData = Containers::Array{NoInit, 2*vertexCount*sizeof(UnsignedInt)}; generateLineLoopIndicesInto(vertexCount, Containers::arrayCast(indexData)); } else if(data.primitive() == MeshPrimitive::TriangleStrip) { primitive = MeshPrimitive::Triangles; - indexData = Containers::Array{Containers::NoInit, 3*(vertexCount - 2)*sizeof(UnsignedInt)}; + indexData = Containers::Array{NoInit, 3*(vertexCount - 2)*sizeof(UnsignedInt)}; generateTriangleStripIndicesInto(vertexCount, Containers::arrayCast(indexData)); } else if(data.primitive() == MeshPrimitive::TriangleFan) { primitive = MeshPrimitive::Triangles; - indexData = Containers::Array{Containers::NoInit, 3*(vertexCount - 2)*sizeof(UnsignedInt)}; + indexData = Containers::Array{NoInit, 3*(vertexCount - 2)*sizeof(UnsignedInt)}; generateTriangleFanIndicesInto(vertexCount, Containers::arrayCast(indexData)); } else CORRADE_ASSERT_UNREACHABLE("MeshTools::generateIndices(): invalid primitive" << data.primitive(), (Trade::MeshData{MeshPrimitive::Triangles, 0})); diff --git a/src/Magnum/MeshTools/GenerateNormals.cpp b/src/Magnum/MeshTools/GenerateNormals.cpp index 31264ed82..214300d50 100644 --- a/src/Magnum/MeshTools/GenerateNormals.cpp +++ b/src/Magnum/MeshTools/GenerateNormals.cpp @@ -53,7 +53,7 @@ void generateFlatNormalsInto(const Containers::StridedArrayView1D } Containers::Array generateFlatNormals(const Containers::StridedArrayView1D& positions) { - Containers::Array out{Containers::NoInit, positions.size()}; + Containers::Array out{NoInit, positions.size()}; generateFlatNormalsInto(positions, Containers::arrayView(out)); return out; } @@ -120,7 +120,7 @@ template inline void generateSmoothNormalsIntoImplementation(const Cont /* Turn that into a running offset array: triangleOffset[i + 1] - triangleOffset[i] is triangle count for vertex i triangleOffset[i] is offset into an triangle ID array for vertex i */ - Containers::Array triangleOffset{Containers::NoInit, positions.size() + 1}; + Containers::Array triangleOffset{NoInit, positions.size() + 1}; triangleOffset[0] = 0; for(std::size_t i = 0; i != triangleCount.size(); ++i) triangleOffset[i + 1] = triangleOffset[i] + triangleCount[i]; @@ -130,7 +130,7 @@ template inline void generateSmoothNormalsIntoImplementation(const Cont /* Gather triangle IDs for every vertex. For vertex i, triangleIds[triangleOffset[i]] until triangleIds[triangleOffset[i + 1]] contains IDs of triangles that contain it. */ - Containers::Array triangleIds{Containers::NoInit, indices.size()}; + Containers::Array triangleIds{NoInit, indices.size()}; for(std::size_t i = 0; i != indices.size(); ++i) { const T triangleId = i/3; const T vertexId = indices[i]; @@ -251,7 +251,7 @@ void generateSmoothNormalsInto(const Containers::StridedArrayView2D& namespace { template inline Containers::Array generateSmoothNormalsImplementation(const Containers::StridedArrayView1D& indices, const Containers::StridedArrayView1D& positions) { - Containers::Array out{Containers::NoInit, positions.size()}; + Containers::Array out{NoInit, positions.size()}; generateSmoothNormalsInto(indices, positions, out); return out; } @@ -272,7 +272,7 @@ Containers::Array generateSmoothNormals(const Containers::StridedArrayV } Containers::Array generateSmoothNormals(const Containers::StridedArrayView2D& indices, const Containers::StridedArrayView1D& positions) { - Containers::Array out{Containers::NoInit, positions.size()}; + Containers::Array out{NoInit, positions.size()}; generateSmoothNormalsInto(indices, positions, out); return out; } diff --git a/src/Magnum/MeshTools/Implementation/Tipsify.h b/src/Magnum/MeshTools/Implementation/Tipsify.h index 70dbae654..1660c65e4 100644 --- a/src/Magnum/MeshTools/Implementation/Tipsify.h +++ b/src/Magnum/MeshTools/Implementation/Tipsify.h @@ -45,7 +45,7 @@ template void buildAdjacency(const Containers::StridedArrayView1D{Containers::NoInit, vertexCount + 1}; + neighborOffset = Containers::Array{NoInit, vertexCount + 1}; neighborOffset[0] = 0; UnsignedInt sum = 0; for(std::size_t i = 0; i != vertexCount; ++i) { @@ -55,7 +55,7 @@ template void buildAdjacency(const Containers::StridedArrayView1D{Containers::NoInit, sum}; + neighbors = Containers::Array{NoInit, sum}; for(std::size_t i = 0; i != indices.size(); ++i) neighbors[neighborOffset[indices[i]+1]++] = i/3; } diff --git a/src/Magnum/MeshTools/Interleave.cpp b/src/Magnum/MeshTools/Interleave.cpp index 0cc73adf5..82565f981 100644 --- a/src/Magnum/MeshTools/Interleave.cpp +++ b/src/Magnum/MeshTools/Interleave.cpp @@ -216,7 +216,7 @@ Trade::MeshData interleavedLayout(Trade::MeshData&& data, const UnsignedInt vert return Trade::MeshData{data.primitive(), vertexCount}; /* Allocate new data array */ - Containers::Array vertexData{Containers::NoInit, attributeData[0].stride()*vertexCount}; + Containers::Array vertexData{NoInit, attributeData[0].stride()*vertexCount}; /* Convert the attributes from offset-only and zero vertex count to absolute, referencing the above-allocated data array */ diff --git a/src/Magnum/MeshTools/Interleave.h b/src/Magnum/MeshTools/Interleave.h index e9f7f0680..974729682 100644 --- a/src/Magnum/MeshTools/Interleave.h +++ b/src/Magnum/MeshTools/Interleave.h @@ -160,7 +160,7 @@ template data{Containers::ValueInit, attributeCount*stride}; + Containers::Array data{ValueInit, attributeCount*stride}; Implementation::writeInterleaved(stride, data.begin(), first, next...); return data; diff --git a/src/Magnum/MeshTools/Reference.cpp b/src/Magnum/MeshTools/Reference.cpp index 80a84adbc..5473cbc5e 100644 --- a/src/Magnum/MeshTools/Reference.cpp +++ b/src/Magnum/MeshTools/Reference.cpp @@ -67,7 +67,7 @@ Trade::MeshData owned(Trade::MeshData&& data) { /* Otherwise copy them, if the mesh is indexed. If not, the default-constructed instances are fine. */ } else if(data.isIndexed()) { - indexData = Containers::Array{Containers::NoInit, data.indexData().size()}; + indexData = Containers::Array{NoInit, data.indexData().size()}; indices = Trade::MeshIndexData{data.indexType(), indexData.slice(data.indexOffset(), data.indexOffset() + data.indexCount()*meshIndexTypeSize(data.indexType()))}; Utility::copy(data.indexData(), indexData); } @@ -83,7 +83,7 @@ Trade::MeshData owned(Trade::MeshData&& data) { /* Otherwise copy them */ } else { - vertexData = Containers::Array{Containers::NoInit, originalVertexData.size()}; + vertexData = Containers::Array{NoInit, originalVertexData.size()}; Utility::copy(originalVertexData, vertexData); } diff --git a/src/Magnum/MeshTools/RemoveDuplicates.cpp b/src/Magnum/MeshTools/RemoveDuplicates.cpp index c6cfcd934..fdb287db3 100644 --- a/src/Magnum/MeshTools/RemoveDuplicates.cpp +++ b/src/Magnum/MeshTools/RemoveDuplicates.cpp @@ -98,7 +98,7 @@ std::size_t removeDuplicatesInto(const Containers::StridedArrayView2D, std::size_t> removeDuplicates(const Containers::StridedArrayView2D& data) { - Containers::Array indices{Containers::NoInit, data.size()[0]}; + Containers::Array indices{NoInit, data.size()[0]}; const std::size_t size = removeDuplicatesInto(data, indices); return {std::move(indices), size}; } @@ -156,7 +156,7 @@ std::size_t removeDuplicatesInPlaceInto(const Containers::StridedArrayView2D, std::size_t> removeDuplicatesInPlace(const Containers::StridedArrayView2D& data) { - Containers::Array indices{Containers::NoInit, data.size()[0]}; + Containers::Array indices{NoInit, data.size()[0]}; const std::size_t size = removeDuplicatesInPlaceInto(data, indices); return {std::move(indices), size}; } @@ -223,7 +223,7 @@ template std::size_t removeDuplicatesFuzzyIndexedInPla to be robust. */ const std::size_t vectorSize = data.size()[1]; T range = T(0.0); - Containers::Array offsets{Containers::NoInit, vectorSize}; + Containers::Array offsets{NoInit, vectorSize}; { /** @todo this isn't really cache-efficient, do differently */ std::size_t i = 0; @@ -249,8 +249,8 @@ template std::size_t removeDuplicatesFuzzyIndexedInPla /* Index array that'll be filled in each pass and then used for remapping the `indices`; discretized storage for all map keys. */ - Containers::Array remapping{Containers::NoInit, dataSize}; - Containers::Array discretized{Containers::NoInit, dataSize*vectorSize}; + Containers::Array remapping{NoInit, dataSize}; + Containers::Array discretized{NoInit, dataSize*vectorSize}; /* First go with original coordinates, then move them by epsilon/2 in each dimension. */ @@ -349,7 +349,7 @@ template std::size_t removeDuplicatesFuzzyInPlaceIntoImplementation(con } template std::pair, std::size_t> removeDuplicatesFuzzyInPlaceImplementation(const Containers::StridedArrayView2D& data, const T epsilon) { - Containers::Array indices{Containers::NoInit, data.size()[0]}; + Containers::Array indices{NoInit, data.size()[0]}; const std::size_t size = removeDuplicatesFuzzyInPlaceIntoImplementation(data, indices, epsilon); return {std::move(indices), size}; } @@ -425,7 +425,7 @@ Trade::MeshData removeDuplicates(Trade::MeshData&& data) { indexData = ownedInterleaved.releaseIndexData(); indexType = ownedInterleaved.indexType(); } else { - indexData = Containers::Array{Containers::NoInit, ownedInterleaved.vertexCount()*sizeof(UnsignedInt)}; + indexData = Containers::Array{NoInit, ownedInterleaved.vertexCount()*sizeof(UnsignedInt)}; uniqueVertexCount = removeDuplicatesInPlaceInto(vertexData, Containers::arrayCast(indexData)); indexType = MeshIndexType::UnsignedInt; } @@ -435,7 +435,7 @@ Trade::MeshData removeDuplicates(Trade::MeshData&& data) { or interleave() above, arrayResize() wouldn't release the excessive memory in any way. This is basically equivalent to STL's shrink_to_fit(), which also copies */ - Containers::Array uniqueVertexData{Containers::NoInit, uniqueVertexCount*vertexData.size()[1]}; + Containers::Array uniqueVertexData{NoInit, uniqueVertexCount*vertexData.size()[1]}; Utility::copy(vertexData.prefix(uniqueVertexCount), Containers::StridedArrayView2D{uniqueVertexData, {uniqueVertexCount, vertexData.size()[1]}}); diff --git a/src/Magnum/MeshTools/Subdivide.h b/src/Magnum/MeshTools/Subdivide.h index df1f75bdc..e3ed60904 100644 --- a/src/Magnum/MeshTools/Subdivide.h +++ b/src/Magnum/MeshTools/Subdivide.h @@ -64,8 +64,8 @@ vertices in the mesh is up to the user. template void subdivide(Containers::Array& indices, Containers::Array& vertices, Interpolator interpolator) { CORRADE_ASSERT(!(indices.size()%3), "MeshTools::subdivide(): index count is not divisible by 3", ); - arrayResize(vertices, Containers::NoInit, vertices.size() + indices.size()); - arrayResize(indices, Containers::NoInit, indices.size()*4); + arrayResize(vertices, NoInit, vertices.size() + indices.size()); + arrayResize(indices, NoInit, indices.size()*4); subdivideInPlace(Containers::stridedArrayView(indices), Containers::stridedArrayView(vertices), interpolator); } diff --git a/src/Magnum/MeshTools/Test/ConcatenateTest.cpp b/src/Magnum/MeshTools/Test/ConcatenateTest.cpp index cf57e0b09..1827a75f1 100644 --- a/src/Magnum/MeshTools/Test/ConcatenateTest.cpp +++ b/src/Magnum/MeshTools/Test/ConcatenateTest.cpp @@ -379,9 +379,9 @@ void ConcatenateTest::concatenateInto() { Containers::Array attributeData{2}; Containers::Array vertexData; Containers::Array indexData; - arrayResize(vertexData, Containers::DirectInit, (sizeof(Vector2) + sizeof(Vector3))*7, '\xff'); + arrayResize(vertexData, DirectInit, (sizeof(Vector2) + sizeof(Vector3))*7, '\xff'); arrayResize(vertexData, 0); - arrayResize(indexData, Containers::DirectInit, sizeof(UnsignedInt)*9, '\xff'); + arrayResize(indexData, DirectInit, sizeof(UnsignedInt)*9, '\xff'); arrayResize(indexData, 0); const void* attributeDataPointer = attributeData; const void* vertexDataPointer = vertexData; diff --git a/src/Magnum/MeshTools/Test/FullScreenTriangleGLTest.cpp b/src/Magnum/MeshTools/Test/FullScreenTriangleGLTest.cpp index fd02a123c..79e648fd7 100644 --- a/src/Magnum/MeshTools/Test/FullScreenTriangleGLTest.cpp +++ b/src/Magnum/MeshTools/Test/FullScreenTriangleGLTest.cpp @@ -133,12 +133,12 @@ void main() { using namespace Math::Literals; Image2D image = framebuffer.read({{}, Vector2i{4}}, PixelFormat::RGBA8Unorm); - CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), Containers::arrayView(Containers::Array{Containers::InPlaceInit, { + CORRADE_COMPARE_AS(Containers::arrayCast(image.data()), Containers::arrayView({ 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba, 0xff80ff80_rgba - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); } }}}} diff --git a/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp b/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp index 969c4bdc0..e916b465d 100644 --- a/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp +++ b/src/Magnum/MeshTools/Test/GenerateNormalsTest.cpp @@ -366,11 +366,11 @@ void GenerateNormalsTest::smoothZeroAreaTriangle() { }; CORRADE_COMPARE_AS(generateSmoothNormals(indices, positions), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ Vector3::zAxis(), Vector3::zAxis(), Vector3::zAxis() - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); } void GenerateNormalsTest::smoothNanPosition() { @@ -442,7 +442,7 @@ void GenerateNormalsTest::benchmarkFlat() { Containers::stridedArrayView(BeveledCubeIndices), Containers::stridedArrayView(BeveledCubePositions)); - Containers::Array normals{Containers::NoInit, positions.size()}; + Containers::Array normals{NoInit, positions.size()}; CORRADE_BENCHMARK(10) { generateFlatNormalsInto(positions, normals); } @@ -451,7 +451,7 @@ void GenerateNormalsTest::benchmarkFlat() { } void GenerateNormalsTest::benchmarkSmooth() { - Containers::Array normals{Containers::NoInit, Containers::arraySize(BeveledCubePositions)}; + Containers::Array normals{NoInit, Containers::arraySize(BeveledCubePositions)}; CORRADE_BENCHMARK(10) { generateSmoothNormalsInto(BeveledCubeIndices, BeveledCubePositions, normals); } diff --git a/src/Magnum/MeshTools/Test/InterleaveTest.cpp b/src/Magnum/MeshTools/Test/InterleaveTest.cpp index 4d76589e5..77bf86d21 100644 --- a/src/Magnum/MeshTools/Test/InterleaveTest.cpp +++ b/src/Magnum/MeshTools/Test/InterleaveTest.cpp @@ -233,7 +233,7 @@ void InterleaveTest::interleaveEmpty() { } void InterleaveTest::interleaveInto() { - Containers::Array data{Containers::InPlaceInit, { + Containers::Array data{InPlaceInit, { 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, 0x11, 0x33, 0x55, 0x77, diff --git a/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp b/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp index fbdec37a9..69d2fb905 100644 --- a/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp +++ b/src/Magnum/MeshTools/Test/RemoveDuplicatesTest.cpp @@ -441,7 +441,7 @@ template void RemoveDuplicatesTest::removeDuplicatesFuzzyInPlaceInto() {T(1.0), T(5.0)} }; - Containers::Array indices{Containers::NoInit, Containers::arraySize(data)}; + Containers::Array indices{NoInit, Containers::arraySize(data)}; std::size_t result = MeshTools::removeDuplicatesFuzzyInPlaceInto( Containers::arrayCast<2, T>(Containers::stridedArrayView(data)), indices, T(2.0)); diff --git a/src/Magnum/MeshTools/Test/SubdivideTest.cpp b/src/Magnum/MeshTools/Test/SubdivideTest.cpp index f57496203..080fc7428 100644 --- a/src/Magnum/MeshTools/Test/SubdivideTest.cpp +++ b/src/Magnum/MeshTools/Test/SubdivideTest.cpp @@ -173,11 +173,11 @@ void SubdivideTest::benchmark() { CORRADE_BENCHMARK(3) { Containers::Array indices; - arrayResize(indices, Containers::NoInit, icosphere.indexCount()); + arrayResize(indices, NoInit, icosphere.indexCount()); Utility::copy(icosphere.indices(), indices); Containers::Array positions; - arrayResize(positions, Containers::NoInit, icosphere.vertexCount()); + arrayResize(positions, NoInit, icosphere.vertexCount()); Utility::copy(icosphere.attribute(Trade::MeshAttribute::Position), positions); /* Subdivide 5 times */ diff --git a/src/Magnum/MeshTools/Tipsify.cpp b/src/Magnum/MeshTools/Tipsify.cpp index 6c301499f..d27e87194 100644 --- a/src/Magnum/MeshTools/Tipsify.cpp +++ b/src/Magnum/MeshTools/Tipsify.cpp @@ -49,7 +49,7 @@ template void tipsifyInPlaceImplementation(const Containers::StridedArr Containers::Array deadEndStack; /* Output index buffer */ - Containers::Array outputIndices{Containers::NoInit, indices.size()}; + Containers::Array outputIndices{NoInit, indices.size()}; std::size_t outputIndex = 0; /* Array with candidates for next fanning vertex (in 1-ring around diff --git a/src/Magnum/MeshTools/sceneconverter.cpp b/src/Magnum/MeshTools/sceneconverter.cpp index 770f943fc..fcb3f58c6 100644 --- a/src/Magnum/MeshTools/sceneconverter.cpp +++ b/src/Magnum/MeshTools/sceneconverter.cpp @@ -468,7 +468,7 @@ used.)") break; } - arrayAppend(info.attributes, Containers::InPlaceInit, + arrayAppend(info.attributes, InPlaceInit, mesh->attributeOffset(k), mesh->attributeStride(k), mesh->attributeArraySize(k), diff --git a/src/Magnum/Platform/AbstractXApplication.cpp b/src/Magnum/Platform/AbstractXApplication.cpp index d816e8363..b07188318 100644 --- a/src/Magnum/Platform/AbstractXApplication.cpp +++ b/src/Magnum/Platform/AbstractXApplication.cpp @@ -41,7 +41,7 @@ AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandle create(configuration, glConfiguration); } -AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, NoCreateT): _contextHandler{contextHandler}, _context{Containers::InPlaceInit, NoCreate, arguments.argc, arguments.argv}, _flags{Flag::Redraw} {} +AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, NoCreateT): _contextHandler{contextHandler}, _context{InPlaceInit, NoCreate, arguments.argc, arguments.argv}, _flags{Flag::Redraw} {} void AbstractXApplication::create() { create({}); } diff --git a/src/Magnum/Platform/AndroidApplication.cpp b/src/Magnum/Platform/AndroidApplication.cpp index f3ee497f0..d70dccbd2 100644 --- a/src/Magnum/Platform/AndroidApplication.cpp +++ b/src/Magnum/Platform/AndroidApplication.cpp @@ -70,7 +70,7 @@ AndroidApplication::AndroidApplication(const Arguments& arguments, const Configu create(configuration, glConfiguration); } -AndroidApplication::AndroidApplication(const Arguments& arguments, NoCreateT): _state{arguments}, _context{Containers::InPlaceInit, NoCreate} { +AndroidApplication::AndroidApplication(const Arguments& arguments, NoCreateT): _state{arguments}, _context{InPlaceInit, NoCreate} { /* Redirect debug output to Android log */ _logOutput.reset(new LogOutput); } diff --git a/src/Magnum/Primitives/Circle.cpp b/src/Magnum/Primitives/Circle.cpp index d078829ff..3d1b6789d 100644 --- a/src/Magnum/Primitives/Circle.cpp +++ b/src/Magnum/Primitives/Circle.cpp @@ -132,7 +132,7 @@ Trade::MeshData circle3DSolid(const UnsignedInt segments, const Circle3DFlags fl } /* Set up the layout */ - Containers::Array vertexData{Containers::NoInit, (segments + 2)*stride}; + Containers::Array vertexData{NoInit, (segments + 2)*stride}; Containers::Array attributeData{attributeCount}; std::size_t attributeIndex = 0; std::size_t attributeOffset = 0; diff --git a/src/Magnum/Primitives/Icosphere.cpp b/src/Magnum/Primitives/Icosphere.cpp index 8ce558e31..839146c9f 100644 --- a/src/Magnum/Primitives/Icosphere.cpp +++ b/src/Magnum/Primitives/Icosphere.cpp @@ -96,8 +96,8 @@ Trade::MeshData icosphereSolid(const UnsignedInt subdivisions) { Vector3 normal; }; Containers::Array vertexData; - Containers::arrayResize(vertexData, - Containers::NoInit, sizeof(Vertex)*vertexCount); + Containers::arrayResize(vertexData, NoInit, + sizeof(Vertex)*vertexCount); /* Build up the subdivided positions */ { diff --git a/src/Magnum/Primitives/Plane.cpp b/src/Magnum/Primitives/Plane.cpp index 463a98f42..6fc3e395f 100644 --- a/src/Magnum/Primitives/Plane.cpp +++ b/src/Magnum/Primitives/Plane.cpp @@ -76,7 +76,7 @@ Trade::MeshData planeSolid(const PlaneFlags flags) { } /* Set up the layout */ - Containers::Array vertexData{Containers::NoInit, 4*stride}; + Containers::Array vertexData{NoInit, 4*stride}; Containers::Array attributeData{attributeCount}; std::size_t attributeIndex = 0; std::size_t attributeOffset = 0; diff --git a/src/Magnum/ShaderTools/AbstractConverter.cpp b/src/Magnum/ShaderTools/AbstractConverter.cpp index d5558259c..07520c72f 100644 --- a/src/Magnum/ShaderTools/AbstractConverter.cpp +++ b/src/Magnum/ShaderTools/AbstractConverter.cpp @@ -467,7 +467,7 @@ bool AbstractConverter::linkDataToFile(const std::initializer_list AbstractConverter::linkDataToDataUsingInputFileCallbacks(const char* const prefix, const Containers::ArrayView> filenames) { - Containers::Array>> data{Containers::NoInit, filenames.size()}; + Containers::Array>> data{NoInit, filenames.size()}; /* First load all files. Remember how many of these succeeded so we can close them again after */ @@ -573,7 +573,7 @@ bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView>> data{Containers::NoInit, from.size()}; + Containers::Array>> 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]; @@ -652,7 +652,7 @@ Containers::Array AbstractConverter::doLinkFilesToData(const Containers::A } /** @todo merge the allocations once we have an ArrayTuple */ - Containers::Array>> data{Containers::NoInit, filenames.size()}; + Containers::Array>> 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]; diff --git a/src/Magnum/ShaderTools/shaderconverter.cpp b/src/Magnum/ShaderTools/shaderconverter.cpp index bca984b01..d0c2c0233 100644 --- a/src/Magnum/ShaderTools/shaderconverter.cpp +++ b/src/Magnum/ShaderTools/shaderconverter.cpp @@ -208,7 +208,7 @@ void printSpirvInfo(Containers::ArrayView data) { Debug d; d << "Entrypoint" << entrypoint->name << "(" << Debug::nospace << spvExecutionModelToStage(entrypoint->executionModel) << Debug::nospace << ")" << Debug::newline; - Containers::Array interface{Containers::ValueInit, entrypoint->interfaces.size()}; + Containers::Array interface{ValueInit, entrypoint->interfaces.size()}; ShaderTools::Implementation::spirvEntrypointInterface(data, *entrypoint, interface); for(const ShaderTools::Implementation::SpirvEntrypointInterface& i: interface) { d << " "; @@ -433,11 +433,11 @@ see documentation of a particular converter for more information.)") for(std::size_t i = 0; i != args.arrayValueCount("define"); ++i) { const Containers::Array3 define = args.arrayValue("define", i).partition('='); - arrayAppend(definitions, Containers::InPlaceInit, + arrayAppend(definitions, InPlaceInit, define[0], define[2]); } for(std::size_t i = 0; i != args.arrayValueCount("undefine"); ++i) { - arrayAppend(definitions, Containers::InPlaceInit, + arrayAppend(definitions, InPlaceInit, args.arrayValue("undefine", i), nullptr); } @@ -465,7 +465,7 @@ see documentation of a particular converter for more information.)") if(args.isSet("link")) { arrayReserve(linkInputs, args.arrayValueCount("input")); for(std::size_t i = 0; i != args.arrayValueCount("input"); ++i) - arrayAppend(linkInputs, Containers::InPlaceInit, + arrayAppend(linkInputs, InPlaceInit, ShaderTools::Stage::Unspecified, args.arrayValue("input", i)); } } diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/Phong.cpp index f443eb541..6cb4505a0 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/Phong.cpp @@ -260,11 +260,11 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l setShininess(80.0f); if(flags & Flag::NormalTexture) setNormalTextureScale(1.0f); - setLightPositions(Containers::Array{Containers::DirectInit, lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}}); - Containers::Array colors{Containers::DirectInit, lightCount, Magnum::Color3{1.0f}}; + setLightPositions(Containers::Array{DirectInit, lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}}); + Containers::Array colors{DirectInit, lightCount, Magnum::Color3{1.0f}}; setLightColors(colors); setLightSpecularColors(colors); - setLightRanges(Containers::Array{Containers::DirectInit, lightCount, Constants::inf()}); + setLightRanges(Containers::Array{DirectInit, lightCount, Constants::inf()}); /* Light position is zero by default */ setNormalMatrix(Matrix3x3{Math::IdentityInit}); } @@ -390,7 +390,7 @@ Phong& Phong::setLightPositions(const std::initializer_list positions) #ifdef MAGNUM_BUILD_DEPRECATED Phong& Phong::setLightPositions(const Containers::ArrayView positions) { - Containers::Array fourComponent{Containers::NoInit, positions.size()}; + Containers::Array fourComponent{NoInit, positions.size()}; for(std::size_t i = 0; i != positions.size(); ++i) fourComponent[i] = Vector4{positions[i], 0.0f}; setLightPositions(fourComponent); @@ -431,7 +431,7 @@ Phong& Phong::setLightColors(const Containers::ArrayView c #ifdef MAGNUM_BUILD_DEPRECATED Phong& Phong::setLightColors(const Containers::ArrayView colors) { - Containers::Array threeComponent{Containers::NoInit, colors.size()}; + Containers::Array threeComponent{NoInit, colors.size()}; for(std::size_t i = 0; i != colors.size(); ++i) threeComponent[i] = colors[i].rgb(); setLightColors(threeComponent); diff --git a/src/Magnum/Shaders/Test/FlatGLTest.cpp b/src/Magnum/Shaders/Test/FlatGLTest.cpp index 8cbfaad89..d70caf85b 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -775,7 +775,7 @@ template void FlatGLTest::renderVertexColor2D() { Primitives::Circle2DFlag::TextureCoordinates); /* Highlight a quarter */ - Containers::Array colorData{Containers::DirectInit, circleData.vertexCount(), 0x999999_rgbf}; + Containers::Array colorData{DirectInit, circleData.vertexCount(), 0x999999_rgbf}; for(std::size_t i = 8; i != 16; ++i) colorData[i + 1] = 0xffff99_rgbf*1.5f; @@ -829,7 +829,7 @@ template void FlatGLTest::renderVertexColor3D() { Primitives::UVSphereFlag::TextureCoordinates); /* Highlight the middle rings */ - Containers::Array colorData{Containers::DirectInit, sphereData.vertexCount(), 0x999999_rgbf}; + Containers::Array colorData{DirectInit, sphereData.vertexCount(), 0x999999_rgbf}; for(std::size_t i = 6*33; i != 9*33; ++i) colorData[i + 1] = 0xffff99_rgbf*1.5f; diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index 28da301c0..8a811c711 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -353,7 +353,7 @@ const struct { {"directional", "light-directional.tga", {1.0f, -1.5f, 0.5f, 0.0f}, Color3{1.0f}, Color3{1.0f}, 1.0f, Constants::inf(), - {Containers::InPlaceInit, { + {InPlaceInit, { /* Ambient isn't affected by light direction, otherwise it's a dot product of a normalized direction */ {{40, 40}, 0x222222_rgb + 0xff8080_rgb*dot(Vector3{1.0f, -1.5f, 0.5f}.normalized(), Vector3::zAxis())}, @@ -380,7 +380,7 @@ const struct { {"directional, from back", "light-none.tga", {-1.0f, 1.5f, -0.5f, 0.0f}, Color3{1.0f}, Color3{1.0f}, 1.0f, Constants::inf(), - {Containers::InPlaceInit, { + {InPlaceInit, { /* Only ambient color left */ {{40, 40}, 0x222222_rgb} }}}, @@ -389,13 +389,13 @@ const struct { {"directional, intensity=2", "light-directional-intensity2.tga", {1.0f, -1.5f, 0.5f, 0.0f}, Color3{1.0f}, Color3{1.0f}, 2.0f, 1.0f, - {Containers::InPlaceInit, { + {InPlaceInit, { {{40, 40}, 0x222222_rgb + 0xff8080_rgb*dot(Vector3{1.0f, -1.5f, 0.5f}.normalized(), Vector3::zAxis())*2.0f} }}}, {"point", "light-point.tga", {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, Color3{1.0f}, 1.0f, Constants::inf(), - {Containers::InPlaceInit, { + {InPlaceInit, { /* The range is inf, so it doesn't get fully ambient even at the edge */ {{8, 71}, 0x2c2727_rgb}, @@ -407,21 +407,21 @@ const struct { {"point, specular material color", "light-point-specular-color.tga", {0.75f, -0.75f, -0.75f, 1.0f}, 0x80ff80_rgbf, Color3{1.0f}, 1.0f, Constants::inf(), - {Containers::InPlaceInit, { + {InPlaceInit, { /* Colored specular highlight */ {{60, 19}, 0xc27573_rgb} }}}, {"point, specular light color", "light-point-specular-color.tga", {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, 0x80ff80_rgbf, 1.0f, Constants::inf(), - {Containers::InPlaceInit, { + {InPlaceInit, { /* Colored specular highlight */ {{60, 19}, 0xc27573_rgb} }}}, {"point, attenuated specular", "light-point-attenuated-specular.tga", {1.0f, -1.0f, -0.25f, 1.0f}, Color3{1.0f}, Color3{1.0f}, 1.0f, 2.5f, - {Containers::InPlaceInit, { + {InPlaceInit, { /* Specular highlight shouldn't be brighter than the attenuated intensity */ {{57, 22}, 0xa68787_rgb} @@ -429,7 +429,7 @@ const struct { {"point, range=1.5, specular color", "light-point-range1.5.tga", {0.75f, -0.75f, -0.75f, 1.0f}, Color3{1.0f}, 0x80ff80_rgbf, 1.0f, 1.5f, - {Containers::InPlaceInit, { + {InPlaceInit, { /* Color goes back to ambient at distance = 1.5 */ {{59, 60}, 0x222222_rgb}, {{29, 50}, 0x222222_rgb}, @@ -1071,7 +1071,7 @@ void PhongGLTest::renderTexturedNormal() { Vector3 bitangent; } tangentBitangent{data.tangent, data.bitangent}; GL::Buffer tangents; - tangents.setData(Containers::Array{Containers::DirectInit, 4, tangentBitangent}); + tangents.setData(Containers::Array{DirectInit, 4, tangentBitangent}); plane.addVertexBuffer(tangents, 0, sizeof(TangentBitangent), GL::DynamicAttribute{Shaders::Phong::Tangent4{data.tangentComponents}}); plane.addVertexBuffer(std::move(tangents), sizeof(Vector4), @@ -1148,7 +1148,7 @@ template void PhongGLTest::renderVertexColor() { Primitives::UVSphereFlag::TextureCoordinates); /* Highlight the pole vertices and the middle rings */ - Containers::Array colorData{Containers::DirectInit, sphereData.vertexCount(), 0x999999_rgbf}; + Containers::Array colorData{DirectInit, sphereData.vertexCount(), 0x999999_rgbf}; for(std::size_t i = 0; i != 3*33 + 1; ++i) colorData[sphereData.vertexCount() - i - 1] = 0xff0000_rgbf*5.0f; for(std::size_t i = 6*33; i != 9*33; ++i) diff --git a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp index 16bb823dd..8740beb6f 100644 --- a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp @@ -200,7 +200,7 @@ template void VertexColorGLTest::renderDefaults2D() { Primitives::Circle2DFlag::TextureCoordinates); /* All a single color */ - Containers::Array colorData{Containers::DirectInit, circleData.vertexCount(), 0xffffff_rgbf}; + Containers::Array colorData{DirectInit, circleData.vertexCount(), 0xffffff_rgbf}; GL::Buffer colors; colors.setData(colorData); @@ -241,7 +241,7 @@ template void VertexColorGLTest::renderDefaults3D() { Primitives::UVSphereFlag::TextureCoordinates); /* All a single color */ - Containers::Array colorData{Containers::DirectInit, sphereData.vertexCount(), 0xffffff_rgbf}; + Containers::Array colorData{DirectInit, sphereData.vertexCount(), 0xffffff_rgbf}; GL::Buffer colors; colors.setData(colorData); @@ -274,7 +274,7 @@ template void VertexColorGLTest::render2D() { Primitives::Circle2DFlag::TextureCoordinates); /* Highlight a quarter */ - Containers::Array colorData{Containers::DirectInit, circleData.vertexCount(), 0x9999ff_rgbf}; + Containers::Array colorData{DirectInit, circleData.vertexCount(), 0x9999ff_rgbf}; for(std::size_t i = 8; i != 16; ++i) colorData[i + 1] = 0xffff99_rgbf; @@ -319,7 +319,7 @@ template void VertexColorGLTest::render3D() { Primitives::UVSphereFlag::TextureCoordinates); /* Highlight the middle rings */ - Containers::Array colorData{Containers::DirectInit, sphereData.vertexCount(), 0x9999ff_rgbf}; + Containers::Array colorData{DirectInit, sphereData.vertexCount(), 0x9999ff_rgbf}; for(std::size_t i = 6*33; i != 9*33; ++i) colorData[i + 1] = 0xffff99_rgbf; diff --git a/src/Magnum/Tags.h b/src/Magnum/Tags.h index cd1c5cd5b..1069353d9 100644 --- a/src/Magnum/Tags.h +++ b/src/Magnum/Tags.h @@ -29,7 +29,7 @@ * @brief Tag type @ref Magnum::NoInitT, @ref Magnum::NoCreateT, tag @ref Magnum::NoInit, @ref Magnum::NoCreate */ -#include +#include #include "Magnum/configure.h" @@ -42,7 +42,11 @@ namespace Magnum { Used to distinguish construction with no initialization at all. @see @ref NoInit */ -typedef Corrade::Containers::NoInitT NoInitT; +#ifdef DOXYGEN_GENERATING_OUTPUT +typedef Corrade::NoInitT NoInitT; +#else +using Corrade::NoInitT; +#endif /** @brief No creation tag type @@ -51,7 +55,11 @@ Used to distinguish construction without creating the underlying OpenGL / Vulkan / ... object. @see @ref NoCreate */ -typedef Corrade::Containers::NoCreateT NoCreateT; +#ifdef DOXYGEN_GENERATING_OUTPUT +typedef Corrade::NoCreateT NoCreateT; +#else +using Corrade::NoCreateT; +#endif /** @brief No allocation tag type @@ -77,7 +85,7 @@ Use for construction with no initialization at all. #ifdef DOXYGEN_GENERATING_OUTPUT constexpr NoInitT NoInit{}; #else -using Corrade::Containers::NoInit; +using Corrade::NoInit; #endif /** @@ -92,7 +100,7 @@ overhead), wrap the objects in an @ref Corrade::Containers::Optional. #ifdef DOXYGEN_GENERATING_OUTPUT constexpr NoCreateT NoCreate{}; #else -using Corrade::Containers::NoCreate; +using Corrade::NoCreate; #endif /** diff --git a/src/Magnum/Test/CMakeLists.txt b/src/Magnum/Test/CMakeLists.txt index 30ef374f9..e9623f23d 100644 --- a/src/Magnum/Test/CMakeLists.txt +++ b/src/Magnum/Test/CMakeLists.txt @@ -31,7 +31,8 @@ corrade_add_test(PixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumTestLib) corrade_add_test(PixelStorageTest PixelStorageTest.cpp LIBRARIES Magnum) corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES Magnum) corrade_add_test(SamplerTest SamplerTest.cpp LIBRARIES MagnumTestLib) -corrade_add_test(TagsTest TagsTest.cpp LIBRARIES Magnum) +# Prefixed with project name to avoid conflicts with TagsTest in Corrade +corrade_add_test(MagnumTagsTest TagsTest.cpp LIBRARIES Magnum) # Prefixed with project name to avoid conflicts with VersionTest in Corrade and # other repos @@ -47,7 +48,7 @@ set_target_properties( PixelStorageTest ResourceManagerTest SamplerTest - TagsTest + MagnumTagsTest MagnumVersionTest VertexFormatTest PROPERTIES FOLDER "Magnum/Test") diff --git a/src/Magnum/Test/ImageTest.cpp b/src/Magnum/Test/ImageTest.cpp index b23017236..5e48c0d7a 100644 --- a/src/Magnum/Test/ImageTest.cpp +++ b/src/Magnum/Test/ImageTest.cpp @@ -743,7 +743,7 @@ void ImageTest::pixels1D() { .setAlignment(1) /** @todo alignment 4 expects 17 bytes. what */ .setSkip({3, 0, 0}), PixelFormat::RGB8Unorm, 2, - Containers::Array{Containers::InPlaceInit, { + Containers::Array{InPlaceInit, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, 7, 8 }}}; const Image1D& cimage = image; @@ -772,7 +772,7 @@ void ImageTest::pixels2D() { .setSkip({3, 2, 0}) .setRowLength(6), PixelFormat::RGB8Unorm, {2, 4}, - Containers::Array{Containers::InPlaceInit, { + Containers::Array{InPlaceInit, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, @@ -807,7 +807,7 @@ void ImageTest::pixels3D() { .setRowLength(6) .setImageHeight(7), PixelFormat::RGB8Unorm, {2, 4, 3}, - Containers::Array{Containers::InPlaceInit, { + Containers::Array{InPlaceInit, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/Magnum/Test/ResourceManagerTest.cpp b/src/Magnum/Test/ResourceManagerTest.cpp index 98bab5535..77b9123eb 100644 --- a/src/Magnum/Test/ResourceManagerTest.cpp +++ b/src/Magnum/Test/ResourceManagerTest.cpp @@ -457,7 +457,7 @@ void ResourceManagerTest::loader() { { ResourceManager rm; - Containers::Pointer loaderPtr{Containers::InPlaceInit, rm}; + Containers::Pointer loaderPtr{InPlaceInit, rm}; IntResourceLoader& loader = *loaderPtr; rm.setLoader(std::move(loaderPtr)); @@ -507,7 +507,7 @@ void ResourceManagerTest::loaderSetNullptr() { }; ResourceManager rm; - Containers::Pointer loaderPtr{Containers::InPlaceInit}; + Containers::Pointer loaderPtr{InPlaceInit}; IntResourceLoader& loader = *loaderPtr; rm.setLoader(std::move(loaderPtr)); diff --git a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp index 8be39c0fc..272cc85bc 100644 --- a/src/Magnum/Text/Test/AbstractFontConverterTest.cpp +++ b/src/Magnum/Text/Test/AbstractFontConverterTest.cpp @@ -507,7 +507,7 @@ void AbstractFontConverterTest::exportGlyphCacheToSingleData() { Containers::Array out = converter.exportGlyphCacheToSingleData(dummyGlyphCache); CORRADE_COMPARE_AS(out, - (Containers::Array{Containers::InPlaceInit, {'\xee'}}), + (Containers::Array{InPlaceInit, {'\xee'}}), TestSuite::Compare::Container); } @@ -640,7 +640,7 @@ void AbstractFontConverterTest::exportGlyphCacheToDataThroughSingleData() { CORRADE_COMPARE(ret.size(), 1); CORRADE_COMPARE(ret[0].first, "font.out"); CORRADE_COMPARE_AS(ret[0].second, - (Containers::Array{Containers::InPlaceInit, {'\xee'}}), + (Containers::Array{InPlaceInit, {'\xee'}}), TestSuite::Compare::Container); } @@ -730,8 +730,8 @@ void AbstractFontConverterTest::exportGlyphCacheToFileThroughData() { std::vector>> doExportGlyphCacheToData(AbstractGlyphCache&, const std::string& filename) const override { std::vector>> ret; - ret.emplace_back(filename, Containers::Array{Containers::InPlaceInit, {'\xf0'}}); - ret.emplace_back(filename + ".dat", Containers::Array{Containers::InPlaceInit, {'\xfe', '\xed'}}); + ret.emplace_back(filename, Containers::Array{InPlaceInit, {'\xf0'}}); + ret.emplace_back(filename + ".dat", Containers::Array{InPlaceInit, {'\xfe', '\xed'}}); return ret; } } converter; diff --git a/src/Magnum/Text/Test/RendererGLTest.cpp b/src/Magnum/Text/Test/RendererGLTest.cpp index f099cf627..3013b4013 100644 --- a/src/Magnum/Text/Test/RendererGLTest.cpp +++ b/src/Magnum/Text/Test/RendererGLTest.cpp @@ -192,7 +192,7 @@ void RendererGLTest::renderMesh() { /* Vertex buffer contents */ Containers::Array vertices = vertexBuffer.data(); CORRADE_COMPARE_AS(Containers::arrayCast(vertices), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0.0f + offset.x(), 0.5f + offset.y(), 0.0f, 10.0f, 0.0f + offset.x(), 0.0f + offset.y(), 0.0f, 0.0f, 0.75f + offset.x(), 0.5f + offset.y(), 6.0f, 10.0f, @@ -207,15 +207,15 @@ void RendererGLTest::renderMesh() { 2.75f + offset.x(), -0.5f + offset.y(), 12.0f, 0.0f, 5.0f + offset.x(), 1.0f + offset.y(), 18.0f, 10.0f, 5.0f + offset.x(), -0.5f + offset.y(), 18.0f, 0.0f - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); Containers::Array indices = indexBuffer.data(); CORRADE_COMPARE_AS(Containers::arrayCast(indices), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6, 8, 9, 10, 9, 11, 10 - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); #endif } @@ -236,11 +236,11 @@ void RendererGLTest::renderMeshIndexType() { CORRADE_COMPARE(vertexBuffer.size(), 256*(2 + 2)*4); CORRADE_COMPARE(indicesByte.size(), 64*6); CORRADE_COMPARE_AS(Containers::arrayCast(indicesByte).prefix(18), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6, 8, 9, 10, 9, 11, 10 - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); /* 16-bit indices (260 vertices) */ std::tie(mesh, std::ignore) = Text::Renderer3D::render(font, nullGlyphCache, @@ -250,11 +250,11 @@ void RendererGLTest::renderMeshIndexType() { CORRADE_COMPARE(vertexBuffer.size(), 260*(2 + 2)*4); CORRADE_COMPARE(indicesShort.size(), 65*6*2); CORRADE_COMPARE_AS(Containers::arrayCast(indicesShort).prefix(18), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6, 8, 9, 10, 9, 11, 10 - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); #else CORRADE_SKIP("Can't verify buffer contents on OpenGL ES."); #endif @@ -284,12 +284,12 @@ void RendererGLTest::mutableText() { #ifndef MAGNUM_TARGET_GLES Containers::Array indices = renderer.indexBuffer().data(); CORRADE_COMPARE_AS(Containers::arrayCast(indices).prefix(24), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0, 1, 2, 1, 3, 2, 4, 5, 6, 5, 7, 6, 8, 9, 10, 9, 11, 10, 12, 13, 14, 13, 15, 14 - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); #endif /* Render text */ @@ -305,7 +305,7 @@ void RendererGLTest::mutableText() { #ifndef MAGNUM_TARGET_GLES Containers::Array vertices = renderer.vertexBuffer().data(); CORRADE_COMPARE_AS(Containers::arrayCast(vertices).prefix(48), - (Containers::Array{Containers::InPlaceInit, { + Containers::arrayView({ 0.0f, 0.5f, 0.0f, 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.5f, 6.0f, 10.0f, @@ -320,7 +320,7 @@ void RendererGLTest::mutableText() { 2.75f, -0.5f, 12.0f, 0.0f, 5.0f, 1.0f, 18.0f, 10.0f, 5.0f, -0.5f, 18.0f, 0.0f - }}), TestSuite::Compare::Container); + }), TestSuite::Compare::Container); #endif } diff --git a/src/Magnum/Trade/Implementation/converterUtilities.h b/src/Magnum/Trade/Implementation/converterUtilities.h index a6ef9fa5d..c5f465342 100644 --- a/src/Magnum/Trade/Implementation/converterUtilities.h +++ b/src/Magnum/Trade/Implementation/converterUtilities.h @@ -57,7 +57,7 @@ Containers::Array imageInfo(AbstractImporter& importer, bool& error, error = true; continue; } - arrayAppend(infos, Containers::InPlaceInit, i, j, + arrayAppend(infos, InPlaceInit, i, j, image->isCompressed(), image->isCompressed() ? PixelFormat{} : image->format(), @@ -78,7 +78,7 @@ Containers::Array imageInfo(AbstractImporter& importer, bool& error, error = true; continue; } - arrayAppend(infos, Containers::InPlaceInit, i, j, + arrayAppend(infos, InPlaceInit, i, j, image->isCompressed(), image->isCompressed() ? PixelFormat{} : image->format(), @@ -99,7 +99,7 @@ Containers::Array imageInfo(AbstractImporter& importer, bool& error, error = true; continue; } - arrayAppend(infos, Containers::InPlaceInit, i, j, + arrayAppend(infos, InPlaceInit, i, j, image->isCompressed(), image->isCompressed() ? PixelFormat{} : image->format(), diff --git a/src/Magnum/Trade/Test/AnimationDataTest.cpp b/src/Magnum/Trade/Test/AnimationDataTest.cpp index a1d7a45cc..e32343670 100644 --- a/src/Magnum/Trade/Test/AnimationDataTest.cpp +++ b/src/Magnum/Trade/Test/AnimationDataTest.cpp @@ -116,7 +116,7 @@ void AnimationDataTest::constructTrackData() { nullptr, Animation::Interpolation::Linear, animationInterpolatorFor(Animation::Interpolation::Linear)}}; - AnimationData data{nullptr, Containers::Array{Containers::InPlaceInit, {trackData}}}; + AnimationData data{nullptr, Containers::Array{InPlaceInit, {trackData}}}; CORRADE_COMPARE(data.trackType(0), AnimationTrackType::Vector3); CORRADE_COMPARE(data.trackResultType(0), AnimationTrackType::Vector3); CORRADE_COMPARE(data.trackTargetType(0), AnimationTrackTargetType::Translation3D); @@ -133,7 +133,7 @@ void AnimationDataTest::constructTrackDataResultType() { nullptr, Animation::Interpolation::Linear, animationInterpolatorFor(Animation::Interpolation::Linear)}}; - AnimationData data{nullptr, Containers::Array{Containers::InPlaceInit, {trackData}}}; + AnimationData data{nullptr, Containers::Array{InPlaceInit, {trackData}}}; CORRADE_COMPARE(data.trackType(0), AnimationTrackType::CubicHermite3D); CORRADE_COMPARE(data.trackResultType(0), AnimationTrackType::Vector3); CORRADE_COMPARE(data.trackTargetType(0), AnimationTrackTargetType::Translation3D); @@ -148,7 +148,7 @@ void AnimationDataTest::constructTrackDataTemplate() { nullptr, Animation::Interpolation::Linear, animationInterpolatorFor(Animation::Interpolation::Linear)}}; - AnimationData data{nullptr, Containers::Array{Containers::InPlaceInit, {trackData}}}; + AnimationData data{nullptr, Containers::Array{InPlaceInit, {trackData}}}; CORRADE_COMPARE(data.trackType(0), AnimationTrackType::CubicHermite3D); CORRADE_COMPARE(data.trackResultType(0), AnimationTrackType::Vector3); CORRADE_COMPARE(data.trackTargetType(0), AnimationTrackTargetType::Translation3D); diff --git a/src/Magnum/Trade/Test/MaterialDataTest.cpp b/src/Magnum/Trade/Test/MaterialDataTest.cpp index 746f7ec5d..0c5824543 100644 --- a/src/Magnum/Trade/Test/MaterialDataTest.cpp +++ b/src/Magnum/Trade/Test/MaterialDataTest.cpp @@ -888,7 +888,7 @@ void MaterialDataTest::constructDuplicateAttribute() { CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif - auto attributes = Containers::Array{Containers::InPlaceInit, { + Containers::Array attributes{InPlaceInit, { {MaterialAttribute::DoubleSided, true}, {MaterialAttribute::DiffuseTextureCoordinates, 5u}, {"highlightColor", 0x335566ff_rgbaf}, diff --git a/src/Magnum/Trade/Test/SkinDataTest.cpp b/src/Magnum/Trade/Test/SkinDataTest.cpp index 58e4e18ea..f7deb7780 100644 --- a/src/Magnum/Trade/Test/SkinDataTest.cpp +++ b/src/Magnum/Trade/Test/SkinDataTest.cpp @@ -125,8 +125,8 @@ void SkinDataTest::constructMove() { } void SkinDataTest::release() { - Containers::Array joints{Containers::InPlaceInit, {0, 2, 3}}; - Containers::Array inverseBindMatrices{Containers::InPlaceInit, { + Containers::Array joints{InPlaceInit, {0, 2, 3}}; + Containers::Array inverseBindMatrices{InPlaceInit, { Matrix3::translation(Vector2::yAxis(0.0f)), Matrix3::translation(Vector2::yAxis(2.0f)), Matrix3::translation(Vector2::yAxis(4.0f)) diff --git a/src/Magnum/Vk/DescriptorPool.cpp b/src/Magnum/Vk/DescriptorPool.cpp index aca95238e..ab4ca541f 100644 --- a/src/Magnum/Vk/DescriptorPool.cpp +++ b/src/Magnum/Vk/DescriptorPool.cpp @@ -48,7 +48,7 @@ DescriptorPoolCreateInfo::DescriptorPoolCreateInfo(const UnsignedInt maxSets, co Containers::ArrayView poolSizesCopy; _data = Containers::ArrayTuple{ - {Containers::NoInit, poolSizes.size(), poolSizesCopy} + {NoInit, poolSizes.size(), poolSizesCopy} }; for(std::size_t i = 0; i != poolSizes.size(); ++i) { CORRADE_ASSERT(poolSizes[i].second, diff --git a/src/Magnum/Vk/DescriptorSetLayout.cpp b/src/Magnum/Vk/DescriptorSetLayout.cpp index c6a9becd8..b62c2bc53 100644 --- a/src/Magnum/Vk/DescriptorSetLayout.cpp +++ b/src/Magnum/Vk/DescriptorSetLayout.cpp @@ -46,7 +46,7 @@ DescriptorSetLayoutBinding::DescriptorSetLayoutBinding(const UnsignedInt binding DescriptorSetLayoutBinding::DescriptorSetLayoutBinding(const UnsignedInt binding, const DescriptorType descriptorType, const Containers::ArrayView immutableSamplers, const ShaderStages stages, Flags flags): _binding{}, _flags{VkDescriptorBindingFlags(flags)} { Containers::ArrayView immutableSamplersCopy; _data = Containers::ArrayTuple{ - {Containers::NoInit, immutableSamplers.size(), immutableSamplersCopy} + {NoInit, immutableSamplers.size(), immutableSamplersCopy} }; Utility::copy(immutableSamplers, immutableSamplersCopy); @@ -109,10 +109,10 @@ DescriptorSetLayoutCreateInfo::DescriptorSetLayoutCreateInfo(const Containers::A Containers::ArrayView bindingsCreateInfoView; Containers::ArrayView immutableSamplersCopy; _data = Containers::ArrayTuple{ - {Containers::NoInit, bindings.size(), bindingsCopy}, - {Containers::NoInit, hasBindingFlags ? bindings.size() : 0, bindingFlagsCopy}, - {Containers::ValueInit, hasBindingFlags ? 1u : 0u, bindingsCreateInfoView}, - {Containers::NoInit, immutableSamplerCount, immutableSamplersCopy} + {NoInit, bindings.size(), bindingsCopy}, + {NoInit, hasBindingFlags ? bindings.size() : 0, bindingFlagsCopy}, + {ValueInit, hasBindingFlags ? 1u : 0u, bindingsCreateInfoView}, + {NoInit, immutableSamplerCount, immutableSamplersCopy} }; /* Copy the binding and then for each manually copy and reroute the diff --git a/src/Magnum/Vk/Device.cpp b/src/Magnum/Vk/Device.cpp index 1546130fc..245982a93 100644 --- a/src/Magnum/Vk/Device.cpp +++ b/src/Magnum/Vk/Device.cpp @@ -120,7 +120,7 @@ struct DeviceCreateInfo::State { DeviceProperties properties{NoCreate}; }; -DeviceCreateInfo::DeviceCreateInfo(DeviceProperties& deviceProperties, const ExtensionProperties* extensionProperties, const Flags flags): _physicalDevice{deviceProperties}, _info{}, _state{Containers::InPlaceInit} { +DeviceCreateInfo::DeviceCreateInfo(DeviceProperties& deviceProperties, const ExtensionProperties* extensionProperties, const Flags flags): _physicalDevice{deviceProperties}, _info{}, _state{InPlaceInit} { Utility::Arguments args = Implementation::arguments(); args.parse(deviceProperties._instance->state().argc, deviceProperties._instance->state().argv); @@ -307,7 +307,7 @@ DeviceCreateInfo& DeviceCreateInfo::addEnabledExtensions(const Containers::Array don't get invalidated when the array gets reallocated. */ const char* data; if(!(extension.flags() >= (Containers::StringViewFlag::NullTerminated|Containers::StringViewFlag::Global))) - data = arrayAppend(_state->ownedStrings, Containers::InPlaceInit, + data = arrayAppend(_state->ownedStrings, InPlaceInit, Containers::AllocatedInit, extension).data(); else data = extension.data(); diff --git a/src/Magnum/Vk/DeviceProperties.cpp b/src/Magnum/Vk/DeviceProperties.cpp index f3c2d3786..fd08daaf5 100644 --- a/src/Magnum/Vk/DeviceProperties.cpp +++ b/src/Magnum/Vk/DeviceProperties.cpp @@ -379,7 +379,7 @@ Containers::ArrayView DeviceProperties::queueFam UnsignedInt count; _state->getQueueFamilyPropertiesImplementation(*this, count, nullptr); - _state->queueFamilyProperties = Containers::Array{Containers::ValueInit, count}; + _state->queueFamilyProperties = Containers::Array{ValueInit, count}; for(VkQueueFamilyProperties2& i: _state->queueFamilyProperties) i.sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2; _state->getQueueFamilyPropertiesImplementation(*this, count, _state->queueFamilyProperties); @@ -587,7 +587,7 @@ Containers::Array enumerateDevices(Instance& instance) { /* Fetch device handles, expect the device count didn't change between calls */ - Containers::Array out{Containers::NoInit, count}; + Containers::Array out{NoInit, count}; CORRADE_INTERNAL_ASSERT_OUTPUT(Implementation::enumerateDevicesInto(instance, out) == out.size()); return out; @@ -599,7 +599,7 @@ Containers::Optional tryPickDevice(Instance& instance) { /* Pick the first by default */ if(args.value("device").empty()) { - Containers::Array1 devices{Containers::NoInit}; + Containers::Array1 devices{NoInit}; if(!Implementation::enumerateDevicesInto(instance, devices)) { Error{} << "Vk::tryPickDevice(): no Vulkan devices found"; return {}; @@ -611,7 +611,7 @@ Containers::Optional tryPickDevice(Instance& instance) { /* Pick by ID */ if(args.value("device")[0] >= '0' && args.value("device")[0] <= '9') { const UnsignedInt id = args.value("device"); - Containers::Array devices{Containers::NoInit, id + 1}; + Containers::Array devices{NoInit, id + 1}; const UnsignedInt count = Implementation::enumerateDevicesInto(instance, devices); if(id >= count) { Error{} << "Vk::tryPickDevice(): index" << id << "out of bounds for" << count << "Vulkan devices"; diff --git a/src/Magnum/Vk/Framebuffer.cpp b/src/Magnum/Vk/Framebuffer.cpp index 70f69c14b..438c2f360 100644 --- a/src/Magnum/Vk/Framebuffer.cpp +++ b/src/Magnum/Vk/Framebuffer.cpp @@ -40,7 +40,7 @@ struct FramebufferCreateInfo::State { Containers::Array attachments; }; -FramebufferCreateInfo::FramebufferCreateInfo(const VkRenderPass renderPass, const Containers::ArrayView> attachments, const Vector3i& size, const Flags flags): _info{}, _state{Containers::InPlaceInit} { +FramebufferCreateInfo::FramebufferCreateInfo(const VkRenderPass renderPass, const Containers::ArrayView> attachments, const Vector3i& size, const Flags flags): _info{}, _state{InPlaceInit} { _info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; _info.flags = VkFramebufferCreateFlags(flags); _info.renderPass = renderPass; @@ -52,7 +52,7 @@ FramebufferCreateInfo::FramebufferCreateInfo(const VkRenderPass renderPass, cons /** @todo combine the state and array allocations into one (could use ArrayTuple, however that one includes ArrayView so not much better than including Array directly in the header which I don't want to do) */ - _state->attachments = Containers::Array{Containers::NoInit, attachments.size()}; + _state->attachments = Containers::Array{NoInit, attachments.size()}; for(std::size_t i = 0; i != attachments.size(); ++i) _state->attachments[i] = *attachments[i]; _info.attachmentCount = _state->attachments.size(); diff --git a/src/Magnum/Vk/Implementation/DriverWorkaround.cpp b/src/Magnum/Vk/Implementation/DriverWorkaround.cpp index 3df15b989..1caf65fb5 100644 --- a/src/Magnum/Vk/Implementation/DriverWorkaround.cpp +++ b/src/Magnum/Vk/Implementation/DriverWorkaround.cpp @@ -100,13 +100,13 @@ void disableWorkaround(Containers::Array return; } - arrayAppend(encounteredWorkarounds, Containers::InPlaceInit, found, true); + arrayAppend(encounteredWorkarounds, InPlaceInit, found, true); } Containers::Array> disableAllWorkarounds() { Containers::Array> encounteredWorkarounds; for(const Containers::StringView i: KnownWorkarounds) - arrayAppend(encounteredWorkarounds, Containers::InPlaceInit, i, true); + arrayAppend(encounteredWorkarounds, InPlaceInit, i, true); return encounteredWorkarounds; } @@ -123,7 +123,7 @@ bool isDriverWorkaroundDisabled(Containers::Array vertexInterface, fragmentInterface; Containers::ArrayTuple interfaceData{ - {Containers::ValueInit, vertexEntryPoint->interfaces.size(), vertexInterface}, - {Containers::ValueInit, fragmentEntryPoint->interfaces.size(), fragmentInterface} + {ValueInit, vertexEntryPoint->interfaces.size(), vertexInterface}, + {ValueInit, fragmentEntryPoint->interfaces.size(), fragmentInterface} }; spirvEntrypointInterface(data, *vertexEntryPoint, vertexInterface); spirvEntrypointInterface(data, *fragmentEntryPoint, fragmentInterface); diff --git a/src/Magnum/Vk/Instance.cpp b/src/Magnum/Vk/Instance.cpp index 3134c5858..d89ad4a36 100644 --- a/src/Magnum/Vk/Instance.cpp +++ b/src/Magnum/Vk/Instance.cpp @@ -189,7 +189,7 @@ InstanceCreateInfo& InstanceCreateInfo::addEnabledLayers(const Containers::Array don't get invalidated when the array gets reallocated. */ const char* data; if(!(layer.flags() >= (Containers::StringViewFlag::NullTerminated|Containers::StringViewFlag::Global))) - data = arrayAppend(_state->ownedStrings, Containers::InPlaceInit, + data = arrayAppend(_state->ownedStrings, InPlaceInit, Containers::AllocatedInit, layer).data(); else data = layer.data(); @@ -223,7 +223,7 @@ InstanceCreateInfo& InstanceCreateInfo::addEnabledExtensions(const Containers::A don't get invalidated when the array gets reallocated. */ const char* data; if(!(extension.flags() >= (Containers::StringViewFlag::NullTerminated|Containers::StringViewFlag::Global))) - data = arrayAppend(_state->ownedStrings, Containers::InPlaceInit, + data = arrayAppend(_state->ownedStrings, InPlaceInit, Containers::AllocatedInit, extension).data(); else data = extension.data(); diff --git a/src/Magnum/Vk/Mesh.cpp b/src/Magnum/Vk/Mesh.cpp index d174419df..f304ed758 100644 --- a/src/Magnum/Vk/Mesh.cpp +++ b/src/Magnum/Vk/Mesh.cpp @@ -91,10 +91,10 @@ Mesh::Mesh(MeshLayout&& layout): _layout{std::move(layout)} { if(const UnsignedInt count = _layout.vkPipelineVertexInputStateCreateInfo().vertexBindingDescriptionCount) { _state.emplace(); _state->vertexBufferData = Containers::ArrayTuple{ - {Containers::ValueInit, count, _state->vertexBuffers}, - {Containers::ValueInit, count, _state->vertexBufferOffsets}, - {Containers::ValueInit, count, _state->vertexBufferStrides}, - {Containers::NoInit, count, _state->ownedVertexBuffers} + {ValueInit, count, _state->vertexBuffers}, + {ValueInit, count, _state->vertexBufferOffsets}, + {ValueInit, count, _state->vertexBufferStrides}, + {NoInit, count, _state->ownedVertexBuffers} }; /** @tod use DirectInit once ArrayTuple can do that */ diff --git a/src/Magnum/Vk/Pipeline.cpp b/src/Magnum/Vk/Pipeline.cpp index 217d9fec0..22d7f143e 100644 --- a/src/Magnum/Vk/Pipeline.cpp +++ b/src/Magnum/Vk/Pipeline.cpp @@ -54,7 +54,7 @@ struct RasterizationPipelineCreateInfo::State { VkRect2D scissor; }; -RasterizationPipelineCreateInfo::RasterizationPipelineCreateInfo(const ShaderSet& shaderSet, const MeshLayout& meshLayout, const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass, const UnsignedInt subpass, const UnsignedInt subpassColorAttachmentCount, Flags flags): _info{}, _viewportInfo{}, _rasterizationInfo{}, _multisampleInfo{}, _depthStencilInfo{}, _colorBlendInfo{}, _dynamicInfo{}, _state{Containers::InPlaceInit} { +RasterizationPipelineCreateInfo::RasterizationPipelineCreateInfo(const ShaderSet& shaderSet, const MeshLayout& meshLayout, const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass, const UnsignedInt subpass, const UnsignedInt subpassColorAttachmentCount, Flags flags): _info{}, _viewportInfo{}, _rasterizationInfo{}, _multisampleInfo{}, _depthStencilInfo{}, _colorBlendInfo{}, _dynamicInfo{}, _state{InPlaceInit} { _info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; _info.flags = VkPipelineCreateFlags(flags); _info.stageCount = shaderSet.stages().size(); @@ -82,7 +82,7 @@ RasterizationPipelineCreateInfo::RasterizationPipelineCreateInfo(const ShaderSet _depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; _info.pDepthStencilState = &_depthStencilInfo; - _state->colorBlendAttachments = Containers::Array{Containers::ValueInit, subpassColorAttachmentCount}; + _state->colorBlendAttachments = Containers::Array{ValueInit, subpassColorAttachmentCount}; for(VkPipelineColorBlendAttachmentState& i: _state->colorBlendAttachments) { i.colorWriteMask = VK_COLOR_COMPONENT_R_BIT| VK_COLOR_COMPONENT_G_BIT| @@ -254,7 +254,7 @@ RasterizationPipelineCreateInfo& RasterizationPipelineCreateInfo::setDynamicStat std::size_t count = 0; for(std::size_t i = 0; i != DynamicRasterizationStates::Size; ++i) count += Math::popcount(states.data()[i]); - _state->dynamicStateList = Containers::Array{Containers::NoInit, count}; + _state->dynamicStateList = Containers::Array{NoInit, count}; std::size_t offset = 0; for(std::uint64_t i = 0; i != Containers::arraySize(DynamicRasterizationStateMapping); ++i) diff --git a/src/Magnum/Vk/PipelineLayout.cpp b/src/Magnum/Vk/PipelineLayout.cpp index a4e5bcd9c..f36778811 100644 --- a/src/Magnum/Vk/PipelineLayout.cpp +++ b/src/Magnum/Vk/PipelineLayout.cpp @@ -39,7 +39,7 @@ PipelineLayoutCreateInfo::PipelineLayoutCreateInfo(const Containers::ArrayView descriptorSetLayoutsCopy; _data = Containers::ArrayTuple{ - {Containers::NoInit, descriptorSetLayouts.size(), descriptorSetLayoutsCopy} + {NoInit, descriptorSetLayouts.size(), descriptorSetLayoutsCopy} }; Utility::copy(descriptorSetLayouts, descriptorSetLayoutsCopy); diff --git a/src/Magnum/Vk/Queue.cpp b/src/Magnum/Vk/Queue.cpp index 378437713..50dd8957d 100644 --- a/src/Magnum/Vk/Queue.cpp +++ b/src/Magnum/Vk/Queue.cpp @@ -73,7 +73,7 @@ void Queue::submit(const Containers::ArrayView vkInfos{Containers::NoInit, infos.size()}; + Containers::Array vkInfos{NoInit, infos.size()}; for(std::size_t i = 0; i != infos.size(); ++i) vkInfos[i] = *infos[i]; @@ -140,7 +140,7 @@ SubmitInfo& SubmitInfo::operator=(SubmitInfo&& other) noexcept { SubmitInfo& SubmitInfo::setCommandBuffers(const Containers::ArrayView buffers) { if(!_state) _state.emplace(); - _state->commandBuffers = Containers::Array{Containers::NoInit, buffers.size()}; + _state->commandBuffers = Containers::Array{NoInit, buffers.size()}; Utility::copy(buffers, _state->commandBuffers); _info.commandBufferCount = _state->commandBuffers.size(); _info.pCommandBuffers = _state->commandBuffers; diff --git a/src/Magnum/Vk/RenderPass.cpp b/src/Magnum/Vk/RenderPass.cpp index bbe038415..0d777da9b 100644 --- a/src/Magnum/Vk/RenderPass.cpp +++ b/src/Magnum/Vk/RenderPass.cpp @@ -199,7 +199,7 @@ SubpassDescription::SubpassDescription(const VkSubpassDescription& description): nullptr, description.preserveAttachmentCount, description.pPreserveAttachments -}, _state{Containers::InPlaceInit} { +}, _state{InPlaceInit} { /* Convert all attachment references to the "version 2" format */ setInputAttachmentsInternal({description.pInputAttachments, description.inputAttachmentCount}); setColorAttachmentsInternal({description.pColorAttachments, description.colorAttachmentCount}, {description.pResolveAttachments, description.pResolveAttachments ? description.colorAttachmentCount : 0}); @@ -450,7 +450,7 @@ Containers::Array SubpassDescription::vkSubpassDescription converted VkAttachmentReference instances it needs. Expect the default deleter is used so we don't need to wrap some other below. */ const std::size_t extrasSize = vkSubpassDescriptionExtrasSize(_description); - Containers::Array storage{Containers::NoInit, sizeof(VkSubpassDescription) + extrasSize}; + Containers::Array storage{NoInit, sizeof(VkSubpassDescription) + extrasSize}; CORRADE_INTERNAL_ASSERT(!storage.deleter()); /* Fill it with data and return, faking a size of 1 and with a custom @@ -702,7 +702,7 @@ Containers::Array RenderPassCreateInfo::vkRenderPassCrea /* Allocate an array to fit VkRenderPassCreateInfo together with all extras it needs. Expect the default deleter is used so we don't need to wrap some other below. */ - Containers::Array storage{Containers::NoInit, sizeof(VkRenderPassCreateInfo) + structuresSize + extrasSize}; + Containers::Array storage{NoInit, sizeof(VkRenderPassCreateInfo) + structuresSize + extrasSize}; CORRADE_INTERNAL_ASSERT(!storage.deleter()); /* Copy what can be copied for the output info struct. The pointers will be @@ -889,7 +889,7 @@ RenderPassBeginInfo& RenderPassBeginInfo::clearDepthStencil(const UnsignedInt at RenderPassBeginInfo& RenderPassBeginInfo::clearInternal(const UnsignedInt attachment, const VkClearValue& value) { if(!_state) _state.emplace(); if(_state->clearValues.size() <= attachment) - arrayResize(_state->clearValues, Containers::NoInit, attachment + 1); + arrayResize(_state->clearValues, NoInit, attachment + 1); _state->clearValues[attachment] = value; _info.clearValueCount = _state->clearValues.size(); _info.pClearValues = _state->clearValues; diff --git a/src/Magnum/Vk/Shader.cpp b/src/Magnum/Vk/Shader.cpp index f5b4557ac..64c462730 100644 --- a/src/Magnum/Vk/Shader.cpp +++ b/src/Magnum/Vk/Shader.cpp @@ -137,7 +137,7 @@ VkResult Shader::createImplementationSwiftShaderMultiEntryPointPatching(Device& might not need to copy it, the owned code may also be read-only for whatever reason (memory-mapped location etc). Thus, to prevent issues, we go the safe route and copy always. */ - Containers::Array mutableCode{Containers::NoInit, info.codeSize}; + Containers::Array mutableCode{NoInit, info.codeSize}; Utility::copy(Containers::arrayView(reinterpret_cast(info.pCode), info.codeSize), mutableCode); /* If the code looks like SPIR-V, patch it. If not, supply the original and diff --git a/src/Magnum/Vk/ShaderSet.cpp b/src/Magnum/Vk/ShaderSet.cpp index 06f121ddd..96f7c5c79 100644 --- a/src/Magnum/Vk/ShaderSet.cpp +++ b/src/Magnum/Vk/ShaderSet.cpp @@ -82,7 +82,7 @@ ShaderSet& ShaderSet::addShader(const ShaderStage stage, const VkShaderModule sh if(!_state) _state.emplace(); /* Ensure the data are never SSO'd and so when the array reallocates we don't need to rewire existing name pointers */ - _stages[_stageCount].pName = arrayAppend(_state->entrypointNames, Containers::InPlaceInit, Containers::AllocatedInit, entrypoint).data(); + _stages[_stageCount].pName = arrayAppend(_state->entrypointNames, InPlaceInit, Containers::AllocatedInit, entrypoint).data(); } /* Specialization, also only if there are any to avoid allocating the state @@ -98,8 +98,8 @@ ShaderSet& ShaderSet::addShader(const ShaderStage stage, const VkShaderModule sh /* The data is (currently) always four bytes, so we don't need to do any extra work to calculate the total data size over all specializations */ - const Containers::ArrayView newSpecializationData = arrayAppend(_state->specializationData, Containers::NoInit, specializations.size()*4); - const Containers::ArrayView newSpecializations = arrayAppend(_state->specializations, Containers::NoInit, specializations.size()); + const Containers::ArrayView newSpecializationData = arrayAppend(_state->specializationData, NoInit, specializations.size()*4); + const Containers::ArrayView newSpecializations = arrayAppend(_state->specializations, NoInit, specializations.size()); /* Reroute the existing structures for possible reallocations */ for(std::size_t i = 0; i != _stageCount; ++i) { diff --git a/src/Magnum/Vk/Test/PipelineTest.cpp b/src/Magnum/Vk/Test/PipelineTest.cpp index d34971934..920826140 100644 --- a/src/Magnum/Vk/Test/PipelineTest.cpp +++ b/src/Magnum/Vk/Test/PipelineTest.cpp @@ -306,11 +306,11 @@ void PipelineTest::rasterizationCreateInfoConstructMove() { MeshLayout meshLayout{MeshPrimitive::Triangles}; - Containers::Pointer a{Containers::InPlaceInit, shaderSet, meshLayout, VkPipelineLayout{}, VkRenderPass{}, 0u, 3u}; + Containers::Pointer a{InPlaceInit, shaderSet, meshLayout, VkPipelineLayout{}, VkRenderPass{}, 0u, 3u}; (*a).setViewport(Range3D{}) .setDynamicStates(DynamicRasterizationState::CullMode); - Containers::Pointer b{Containers::InPlaceInit, std::move(*a)}; + Containers::Pointer b{InPlaceInit, std::move(*a)}; CORRADE_COMPARE((**a).stageCount, 0); CORRADE_VERIFY(!(**a).pStages); CORRADE_VERIFY(!(**a).pVertexInputState); @@ -344,7 +344,7 @@ void PipelineTest::rasterizationCreateInfoConstructMove() { CORRADE_VERIFY((**b).pDynamicState); CORRADE_COMPARE((**b).pDynamicState->sType, VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO); - Containers::Pointer c{Containers::InPlaceInit, VkGraphicsPipelineCreateInfo{}}; + Containers::Pointer c{InPlaceInit, VkGraphicsPipelineCreateInfo{}}; *c = std::move(*b); CORRADE_COMPARE((**b).stageCount, 0); CORRADE_VERIFY(!(**b).pStages); diff --git a/src/Magnum/Vk/Test/RenderPassTest.cpp b/src/Magnum/Vk/Test/RenderPassTest.cpp index 2432b49a0..653d8a854 100644 --- a/src/Magnum/Vk/Test/RenderPassTest.cpp +++ b/src/Magnum/Vk/Test/RenderPassTest.cpp @@ -242,7 +242,7 @@ template struct Traits; static const char* name() { return #type "2"; } \ /* So we have the same interface in both cases */ \ static Containers::Array convert(const type& instance) { \ - return {Containers::InPlaceInit, {*instance}}; \ + return {InPlaceInit, {*instance}}; \ } \ }; _c(AttachmentDescription) diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp index 26e98ac27..274334d83 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp @@ -49,7 +49,7 @@ struct AnyConverter::State { AnyConverter::AnyConverter(PluginManager::Manager& manager): AbstractConverter{manager} {} -AnyConverter::AnyConverter(PluginManager::AbstractManager& manager, const std::string& plugin): AbstractConverter{manager, plugin}, _state{Containers::InPlaceInit} {} +AnyConverter::AnyConverter(PluginManager::AbstractManager& manager, const std::string& plugin): AbstractConverter{manager, plugin}, _state{InPlaceInit} {} AnyConverter::~AnyConverter() = default; diff --git a/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp b/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp index 9e92f6e67..d6daccd20 100644 --- a/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp +++ b/src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp @@ -125,7 +125,7 @@ void MagnumFontConverterTest::exportFont() { GlyphCacheFeatures doFeatures() const override { return GlyphCacheFeature::ImageDownload; } void doSetImage(const Vector2i&, const ImageView2D&) override {} Image2D doImage() override { - return Image2D{PixelFormat::R8Unorm, Vector2i{256}, Containers::Array{Containers::ValueInit, 256*256}}; + return Image2D{PixelFormat::R8Unorm, Vector2i{256}, Containers::Array{ValueInit, 256*256}}; } } cache; cache.insert(font.glyphId(U'W'), {25, 34}, {{0, 8}, {16, 128}}); diff --git a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp index f5f203876..0fc084ff1 100644 --- a/src/MagnumPlugins/ObjImporter/ObjImporter.cpp +++ b/src/MagnumPlugins/ObjImporter/ObjImporter.cpp @@ -429,7 +429,7 @@ Containers::Optional ObjImporter::doMesh(UnsignedInt id, UnsignedInt) /* Merge index arrays. If any of the attributes was not there, the whole index array has zeros, not affecting the uniqueness in any way. */ - Containers::Array indexData{Containers::NoInit, indices.size()*sizeof(UnsignedInt)}; + Containers::Array indexData{NoInit, indices.size()*sizeof(UnsignedInt)}; const auto indexDataI = Containers::arrayCast(indexData); const std::size_t vertexCount = MeshTools::removeDuplicatesInPlaceInto( Containers::arrayCast<2, char>(arrayView(indices)), indexDataI); @@ -446,7 +446,7 @@ Containers::Optional ObjImporter::doMesh(UnsignedInt id, UnsignedInt) stride += sizeof(Vector2); } Containers::Array attributeData{attributeCount}; - Containers::Array vertexData{Containers::NoInit, vertexCount*stride}; + Containers::Array vertexData{NoInit, vertexCount*stride}; /* Duplicate the vertices into the output */ const auto indicesPerAttribute = Containers::arrayCast<2, const UnsignedInt>(stridedArrayView(indices)).transposed<0, 1>(); diff --git a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp index ca1a4e3c1..6ff0395b9 100644 --- a/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp +++ b/src/MagnumPlugins/TgaImageConverter/TgaImageConverter.cpp @@ -48,7 +48,7 @@ ImageConverterFeatures TgaImageConverter::doFeatures() const { return ImageConve Containers::Array TgaImageConverter::doConvertToData(const ImageView2D& image) { /* Initialize data buffer */ const auto pixelSize = UnsignedByte(image.pixelSize()); - Containers::Array data{Containers::ValueInit, sizeof(Implementation::TgaHeader) + pixelSize*image.size().product()}; + Containers::Array data{ValueInit, sizeof(Implementation::TgaHeader) + pixelSize*image.size().product()}; /* Fill header */ auto header = reinterpret_cast(data.begin()); From a90e67edaa9f99e8fc8718af4b597683b9d6b17d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Apr 2021 15:25:37 +0200 Subject: [PATCH 142/161] DebugTools: rename GLFrameProfiler to FrameProfilerGL. This makes more sense regarding autocompletion and grouping of common things together when sorted alphabetically. Sorry it didn't occur sooner to me. --- doc/changelog.dox | 4 + doc/snippets/MagnumDebugTools-gl.cpp | 10 +- doc/snippets/debugtools-frameprofiler.cpp | 12 +-- src/Magnum/DebugTools/DebugTools.h | 5 +- src/Magnum/DebugTools/FrameProfiler.cpp | 94 +++++++++---------- src/Magnum/DebugTools/FrameProfiler.h | 65 +++++++------ .../DebugTools/Test/FrameProfilerGLTest.cpp | 50 +++++----- .../DebugTools/Test/FrameProfilerTest.cpp | 68 +++++++------- 8 files changed, 161 insertions(+), 147 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 0f31439ec..1794ddd02 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -437,6 +437,10 @@ See also: the canvas and status elements from the JS `Module`. See @ref platforms-html5-apps and [mosra/magnum#481](https://github.com/mosra/magnum/pull/481) for details. +- @cpp DebugTools::GLFrameProfiler @ce is deprecated in favor of + @ref DebugTools::FrameProfilerGL. The new name plays better with IDE + autocompletion and makes the GL-specific class appear next to the + API-independent base in alphabetically sorted lists. - @ref Shaders::Phong::setLightPositions() and @ref Shaders::Phong::setLightPosition() taking three-component vectors are deprecated in favor of variants taking four-component vectors, where the diff --git a/doc/snippets/MagnumDebugTools-gl.cpp b/doc/snippets/MagnumDebugTools-gl.cpp index 28d596163..e3d575071 100644 --- a/doc/snippets/MagnumDebugTools-gl.cpp +++ b/doc/snippets/MagnumDebugTools-gl.cpp @@ -149,11 +149,11 @@ new DebugTools::ObjectRenderer3D{manager, *object, "my", &debugDrawables}; } { -/* [GLFrameProfiler-usage] */ -DebugTools::GLFrameProfiler profiler{ - DebugTools::GLFrameProfiler::Value::FrameTime| - DebugTools::GLFrameProfiler::Value::GpuDuration, 50}; -/* [GLFrameProfiler-usage] */ +/* [FrameProfilerGL-usage] */ +DebugTools::FrameProfilerGL profiler{ + DebugTools::FrameProfilerGL::Value::FrameTime| + DebugTools::FrameProfilerGL::Value::GpuDuration, 50}; +/* [FrameProfilerGL-usage] */ } { diff --git a/doc/snippets/debugtools-frameprofiler.cpp b/doc/snippets/debugtools-frameprofiler.cpp index 07ac18702..9257d5dfc 100644 --- a/doc/snippets/debugtools-frameprofiler.cpp +++ b/doc/snippets/debugtools-frameprofiler.cpp @@ -43,12 +43,12 @@ class FrameProfiler: public Platform::WindowlessApplication { FrameProfiler::FrameProfiler(const Arguments& arguments): Platform::WindowlessApplication{arguments} { /* Enable everything in the GL profiler and then introspect it to fake its output 1:1 */ - DebugTools::GLFrameProfiler glProfiler{ - DebugTools::GLFrameProfiler::Value::FrameTime| - DebugTools::GLFrameProfiler::Value::CpuDuration| - DebugTools::GLFrameProfiler::Value::GpuDuration| - DebugTools::GLFrameProfiler::Value::VertexFetchRatio| - DebugTools::GLFrameProfiler::Value::PrimitiveClipRatio + DebugTools::FrameProfilerGL glProfiler{ + DebugTools::FrameProfilerGL::Value::FrameTime| + DebugTools::FrameProfilerGL::Value::CpuDuration| + DebugTools::FrameProfilerGL::Value::GpuDuration| + DebugTools::FrameProfilerGL::Value::VertexFetchRatio| + DebugTools::FrameProfilerGL::Value::PrimitiveClipRatio , 50}; DebugTools::FrameProfiler profiler{{ diff --git a/src/Magnum/DebugTools/DebugTools.h b/src/Magnum/DebugTools/DebugTools.h index 5bb47690f..7241205ee 100644 --- a/src/Magnum/DebugTools/DebugTools.h +++ b/src/Magnum/DebugTools/DebugTools.h @@ -44,7 +44,10 @@ class CORRADE_DEPRECATED("use FrameProfiler instead") Profiler; class FrameProfiler; #ifdef MAGNUM_TARGET_GL -class GLFrameProfiler; +class FrameProfilerGL; +#ifdef MAGNUM_BUILD_DEPRECATED +typedef CORRADE_DEPRECATED("use FrameProfilerGL instead") FrameProfilerGL GLFrameProfiler; +#endif template class ForceRenderer; typedef ForceRenderer<2> ForceRenderer2D; diff --git a/src/Magnum/DebugTools/FrameProfiler.cpp b/src/Magnum/DebugTools/FrameProfiler.cpp index 95aacdf12..12032a91a 100644 --- a/src/Magnum/DebugTools/FrameProfiler.cpp +++ b/src/Magnum/DebugTools/FrameProfiler.cpp @@ -429,7 +429,7 @@ Debug& operator<<(Debug& debug, const FrameProfiler::Units value) { } #ifdef MAGNUM_TARGET_GL -struct GLFrameProfiler::State { +struct FrameProfilerGL::State { UnsignedShort cpuDurationIndex = 0xffff, gpuDurationIndex = 0xffff, frameTimeIndex = 0xffff; @@ -448,20 +448,20 @@ struct GLFrameProfiler::State { #endif }; -GLFrameProfiler::GLFrameProfiler(): _state{InPlaceInit} {} +FrameProfilerGL::FrameProfilerGL(): _state{InPlaceInit} {} -GLFrameProfiler::GLFrameProfiler(const Values values, const UnsignedInt maxFrameCount): GLFrameProfiler{} +FrameProfilerGL::FrameProfilerGL(const Values values, const UnsignedInt maxFrameCount): FrameProfilerGL{} { setup(values, maxFrameCount); } -GLFrameProfiler::GLFrameProfiler(GLFrameProfiler&&) noexcept = default; +FrameProfilerGL::FrameProfilerGL(FrameProfilerGL&&) noexcept = default; -GLFrameProfiler& GLFrameProfiler::operator=(GLFrameProfiler&&) noexcept = default; +FrameProfilerGL& FrameProfilerGL::operator=(FrameProfilerGL&&) noexcept = default; -GLFrameProfiler::~GLFrameProfiler() = default; +FrameProfilerGL::~FrameProfilerGL() = default; -void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount) { +void FrameProfilerGL::setup(const Values values, const UnsignedInt maxFrameCount) { UnsignedShort index = 0; Containers::Array measurements; if(values & Value::FrameTime) { @@ -565,7 +565,7 @@ void GLFrameProfiler::setup(const Values values, const UnsignedInt maxFrameCount setup(std::move(measurements), maxFrameCount); } -auto GLFrameProfiler::values() const -> Values { +auto FrameProfilerGL::values() const -> Values { Values values; if(_state->frameTimeIndex != 0xffff) values |= Value::FrameTime; if(_state->cpuDurationIndex != 0xffff) values |= Value::CpuDuration; @@ -577,7 +577,7 @@ auto GLFrameProfiler::values() const -> Values { return values; } -bool GLFrameProfiler::isMeasurementAvailable(const Value value) const { +bool FrameProfilerGL::isMeasurementAvailable(const Value value) const { const UnsignedShort* index = nullptr; switch(value) { case Value::FrameTime: index = &_state->frameTimeIndex; break; @@ -590,45 +590,45 @@ bool GLFrameProfiler::isMeasurementAvailable(const Value value) const { } CORRADE_INTERNAL_ASSERT(index); CORRADE_ASSERT(*index < measurementCount(), - "DebugTools::GLFrameProfiler::isMeasurementAvailable():" << value << "not enabled", {}); + "DebugTools::FrameProfilerGL::isMeasurementAvailable():" << value << "not enabled", {}); return isMeasurementAvailable(*index); } -Double GLFrameProfiler::frameTimeMean() const { +Double FrameProfilerGL::frameTimeMean() const { CORRADE_ASSERT(_state->frameTimeIndex < measurementCount(), - "DebugTools::GLFrameProfiler::frameTimeMean(): not enabled", {}); + "DebugTools::FrameProfilerGL::frameTimeMean(): not enabled", {}); return measurementMean(_state->frameTimeIndex); } -Double GLFrameProfiler::cpuDurationMean() const { +Double FrameProfilerGL::cpuDurationMean() const { CORRADE_ASSERT(_state->cpuDurationIndex < measurementCount(), - "DebugTools::GLFrameProfiler::cpuDurationMean(): not enabled", {}); + "DebugTools::FrameProfilerGL::cpuDurationMean(): not enabled", {}); return measurementMean(_state->cpuDurationIndex); } -Double GLFrameProfiler::gpuDurationMean() const { +Double FrameProfilerGL::gpuDurationMean() const { CORRADE_ASSERT(_state->gpuDurationIndex < measurementCount(), - "DebugTools::GLFrameProfiler::gpuDurationMean(): not enabled", {}); + "DebugTools::FrameProfilerGL::gpuDurationMean(): not enabled", {}); return measurementMean(_state->gpuDurationIndex); } #ifndef MAGNUM_TARGET_GLES -Double GLFrameProfiler::vertexFetchRatioMean() const { +Double FrameProfilerGL::vertexFetchRatioMean() const { CORRADE_ASSERT(_state->vertexFetchRatioIndex < measurementCount(), - "DebugTools::GLFrameProfiler::vertexFetchRatioMean(): not enabled", {}); + "DebugTools::FrameProfilerGL::vertexFetchRatioMean(): not enabled", {}); return measurementMean(_state->vertexFetchRatioIndex); } -Double GLFrameProfiler::primitiveClipRatioMean() const { +Double FrameProfilerGL::primitiveClipRatioMean() const { CORRADE_ASSERT(_state->primitiveClipRatioIndex < measurementCount(), - "DebugTools::GLFrameProfiler::primitiveClipRatioMean(): not enabled", {}); + "DebugTools::FrameProfilerGL::primitiveClipRatioMean(): not enabled", {}); return measurementMean(_state->primitiveClipRatioIndex); } #endif namespace { -constexpr const char* GLFrameProfilerValueNames[] { +constexpr const char* FrameProfilerGLValueNames[] { "FrameTime", "CpuDuration", "GpuDuration", @@ -638,24 +638,24 @@ constexpr const char* GLFrameProfilerValueNames[] { } -Debug& operator<<(Debug& debug, const GLFrameProfiler::Value value) { - debug << "DebugTools::GLFrameProfiler::Value" << Debug::nospace; +Debug& operator<<(Debug& debug, const FrameProfilerGL::Value value) { + debug << "DebugTools::FrameProfilerGL::Value" << Debug::nospace; const UnsignedInt bit = Math::log2(UnsignedShort(value)); if(1 << bit == UnsignedShort(value)) - return debug << "::" << Debug::nospace << GLFrameProfilerValueNames[bit]; + return debug << "::" << Debug::nospace << FrameProfilerGLValueNames[bit]; return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedShort(value)) << Debug::nospace << ")"; } -Debug& operator<<(Debug& debug, const GLFrameProfiler::Values value) { - return Containers::enumSetDebugOutput(debug, value, "DebugTools::GLFrameProfiler::Values{}", { - GLFrameProfiler::Value::FrameTime, - GLFrameProfiler::Value::CpuDuration, - GLFrameProfiler::Value::GpuDuration, +Debug& operator<<(Debug& debug, const FrameProfilerGL::Values value) { + return Containers::enumSetDebugOutput(debug, value, "DebugTools::FrameProfilerGL::Values{}", { + FrameProfilerGL::Value::FrameTime, + FrameProfilerGL::Value::CpuDuration, + FrameProfilerGL::Value::GpuDuration, #ifndef MAGNUM_TARGET_GLES - GLFrameProfiler::Value::VertexFetchRatio, - GLFrameProfiler::Value::PrimitiveClipRatio + FrameProfilerGL::Value::VertexFetchRatio, + FrameProfilerGL::Value::PrimitiveClipRatio #endif }); } @@ -668,43 +668,43 @@ namespace Corrade { namespace Utility { using namespace Magnum; #ifdef MAGNUM_TARGET_GL -std::string ConfigurationValue::toString(const DebugTools::GLFrameProfiler::Value value, ConfigurationValueFlags) { +std::string ConfigurationValue::toString(const DebugTools::FrameProfilerGL::Value value, ConfigurationValueFlags) { const UnsignedInt bit = Math::log2(UnsignedShort(value)); if(1 << bit == UnsignedShort(value)) - return DebugTools::GLFrameProfilerValueNames[bit]; + return DebugTools::FrameProfilerGLValueNames[bit]; return ""; } -DebugTools::GLFrameProfiler::Value ConfigurationValue::fromString(const std::string& value, ConfigurationValueFlags) { - for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i) - if(DebugTools::GLFrameProfilerValueNames[i] == value) - return DebugTools::GLFrameProfiler::Value(1 << i); +DebugTools::FrameProfilerGL::Value ConfigurationValue::fromString(const std::string& value, ConfigurationValueFlags) { + for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i) + if(DebugTools::FrameProfilerGLValueNames[i] == value) + return DebugTools::FrameProfilerGL::Value(1 << i); - return DebugTools::GLFrameProfiler::Value{}; + return DebugTools::FrameProfilerGL::Value{}; } -std::string ConfigurationValue::toString(const DebugTools::GLFrameProfiler::Values value, ConfigurationValueFlags) { +std::string ConfigurationValue::toString(const DebugTools::FrameProfilerGL::Values value, ConfigurationValueFlags) { std::string out; - for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i) { - const auto bit = DebugTools::GLFrameProfiler::Value(1 << i); + for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i) { + const auto bit = DebugTools::FrameProfilerGL::Value(1 << i); if(value & bit) { if(!out.empty()) out += ' '; - out += DebugTools::GLFrameProfilerValueNames[i]; + out += DebugTools::FrameProfilerGLValueNames[i]; } } return out; } -DebugTools::GLFrameProfiler::Values ConfigurationValue::fromString(const std::string& value, ConfigurationValueFlags) { +DebugTools::FrameProfilerGL::Values ConfigurationValue::fromString(const std::string& value, ConfigurationValueFlags) { const std::vector bits = Utility::String::splitWithoutEmptyParts(value); - DebugTools::GLFrameProfiler::Values values; + DebugTools::FrameProfilerGL::Values values; for(const std::string& bit: bits) - for(std::size_t i = 0; i != Containers::arraySize(DebugTools::GLFrameProfilerValueNames); ++i) - if(DebugTools::GLFrameProfilerValueNames[i] == bit) - values |= DebugTools::GLFrameProfiler::Value(1 << i); + for(std::size_t i = 0; i != Containers::arraySize(DebugTools::FrameProfilerGLValueNames); ++i) + if(DebugTools::FrameProfilerGLValueNames[i] == bit) + values |= DebugTools::FrameProfilerGL::Value(1 << i); return values; } diff --git a/src/Magnum/DebugTools/FrameProfiler.h b/src/Magnum/DebugTools/FrameProfiler.h index e322ccf20..5b6abea1c 100644 --- a/src/Magnum/DebugTools/FrameProfiler.h +++ b/src/Magnum/DebugTools/FrameProfiler.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::DebugTools::FrameProfiler, @ref Magnum::DebugTools::GLFrameProfiler + * @brief Class @ref Magnum::DebugTools::FrameProfiler, @ref Magnum::DebugTools::FrameProfilerGL * @m_since{2020,06} */ @@ -46,7 +46,7 @@ namespace Magnum { namespace DebugTools { A generic implementation of a frame profiler supporting a moving average over a set of frames as well as delayed measurements to avoid stalls when querying the results. This class alone doesn't provide any pre-defined measurements, see -for example @ref GLFrameProfiler that provides common measurements like CPU and +for example @ref FrameProfilerGL that provides common measurements like CPU and GPU time. @experimental @@ -78,13 +78,13 @@ frames: @snippet MagnumDebugTools.cpp FrameProfiler-usage-console And here's a sample output on the terminal --- using a fully configured -@link GLFrameProfiler @endlink: +@link FrameProfilerGL @endlink: @include debugtools-frameprofiler.ansi @section DebugTools-FrameProfiler-setup Setting up measurements -Unless you're using this class through @ref GLFrameProfiler, measurements +Unless you're using this class through @ref FrameProfilerGL, measurements have to be set up by passing @ref Measurement instances to the @ref setup() function or to the constructor, together with specifying count of frames for the moving average. A CPU duration measurements using the @ref std::chrono APIs @@ -499,7 +499,7 @@ A @ref FrameProfiler with OpenGL-specific measurements. Instantiate with a desired subset of measured values and then continue the same way as described in the @ref DebugTools-FrameProfiler-usage "FrameProfiler usage documentation": -@snippet MagnumDebugTools-gl.cpp GLFrameProfiler-usage +@snippet MagnumDebugTools-gl.cpp FrameProfilerGL-usage If none if @ref Value::GpuDuration, @ref Value::VertexFetchRatio and @ref Value::PrimitiveClipRatio is not enabled, the class can operate without an @@ -507,12 +507,12 @@ active OpenGL context. @experimental */ -class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler { +class MAGNUM_DEBUGTOOLS_EXPORT FrameProfilerGL: public FrameProfiler { public: /** * @brief Measured value * - * @see @ref Values, @ref GLFrameProfiler(Values, UnsignedInt), + * @see @ref Values, @ref FrameProfilerGL(Values, UnsignedInt), * @ref setup() */ enum class Value: UnsignedShort { @@ -572,7 +572,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler { /** * @brief Measured values * - * @see @ref GLFrameProfiler(Values, UnsignedInt), @ref setup() + * @see @ref FrameProfilerGL(Values, UnsignedInt), @ref setup() */ typedef Containers::EnumSet Values; @@ -581,7 +581,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler { * * Call @ref setup() to populate the profiler with measurements. */ - explicit GLFrameProfiler(); + explicit FrameProfilerGL(); /** * @brief Constructor @@ -589,21 +589,21 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler { * Equivalent to default-constructing an instance and calling * @ref setup() afterwards. */ - explicit GLFrameProfiler(Values values, UnsignedInt maxFrameCount); + explicit FrameProfilerGL(Values values, UnsignedInt maxFrameCount); /** @brief Copying is not allowed */ - GLFrameProfiler(const GLFrameProfiler&) = delete; + FrameProfilerGL(const FrameProfilerGL&) = delete; /** @brief Move constructor */ - GLFrameProfiler(GLFrameProfiler&&) noexcept; + FrameProfilerGL(FrameProfilerGL&&) noexcept; /** @brief Copying is not allowed */ - GLFrameProfiler& operator=(const GLFrameProfiler&) = delete; + FrameProfilerGL& operator=(const FrameProfilerGL&) = delete; /** @brief Move assignment */ - GLFrameProfiler& operator=(GLFrameProfiler&&) noexcept; + FrameProfilerGL& operator=(FrameProfilerGL&&) noexcept; - ~GLFrameProfiler(); + ~FrameProfilerGL(); /** * @brief Setup measured values @@ -621,7 +621,7 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler { * @brief Measured values * * Corresponds to the @p values parameter passed to - * @ref GLFrameProfiler(Values, UnsignedInt) or @ref setup(). + * @ref FrameProfilerGL(Values, UnsignedInt) or @ref setup(). */ Values values() const; @@ -696,19 +696,26 @@ class MAGNUM_DEBUGTOOLS_EXPORT GLFrameProfiler: public FrameProfiler { Containers::Pointer _state; }; -CORRADE_ENUMSET_OPERATORS(GLFrameProfiler::Values) +CORRADE_ENUMSET_OPERATORS(FrameProfilerGL::Values) /** -@debugoperatorclassenum{GLFrameProfiler,GLFrameProfiler::Value} +@debugoperatorclassenum{FrameProfilerGL,FrameProfilerGL::Value} @m_since{2020,06} */ -MAGNUM_DEBUGTOOLS_EXPORT Debug& operator<<(Debug& debug, GLFrameProfiler::Value value); +MAGNUM_DEBUGTOOLS_EXPORT Debug& operator<<(Debug& debug, FrameProfilerGL::Value value); /** -@debugoperatorclassenum{GLFrameProfiler,GLFrameProfiler::Values} +@debugoperatorclassenum{FrameProfilerGL,FrameProfilerGL::Values} @m_since{2020,06} */ -MAGNUM_DEBUGTOOLS_EXPORT Debug& operator<<(Debug& debug, GLFrameProfiler::Values value); +MAGNUM_DEBUGTOOLS_EXPORT Debug& operator<<(Debug& debug, FrameProfilerGL::Values value); + +#ifdef MAGNUM_BUILD_DEPRECATED +/** @brief @copybrief FrameProfilerGL + * @m_deprecated_since_latest Use @ref FrameProfilerGL instead. + */ +typedef CORRADE_DEPRECATED("use FrameProfilerGL instead") FrameProfilerGL GLFrameProfiler; +#endif #endif }} @@ -717,10 +724,10 @@ namespace Corrade { namespace Utility { #ifdef MAGNUM_TARGET_GL /** -@configurationvalue{Magnum::DebugTools::GLFrameProfiler::Value} +@configurationvalue{Magnum::DebugTools::FrameProfilerGL::Value} @m_since{2020,06} */ -template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue { +template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue { ConfigurationValue() = delete; /** @@ -728,21 +735,21 @@ template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue { +template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue { ConfigurationValue() = delete; /** @@ -751,7 +758,7 @@ template<> struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue struct MAGNUM_DEBUGTOOLS_EXPORT ConfigurationValue()) CORRADE_SKIP(GL::Extensions::ARB::timer_query::string() << "is not supported."); @@ -92,7 +92,7 @@ void FrameProfilerGLTest::test() { } #ifndef MAGNUM_TARGET_GLES - if((data.values & GLFrameProfiler::Value::VertexFetchRatio) && !GL::Context::current().isExtensionSupported()) + if((data.values & FrameProfilerGL::Value::VertexFetchRatio) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported."); #endif @@ -112,15 +112,15 @@ void FrameProfilerGLTest::test() { Shaders::Flat3D shader; GL::Mesh mesh = MeshTools::compile(Primitives::cubeSolid()); - GLFrameProfiler profiler{data.values, 4}; + FrameProfilerGL profiler{data.values, 4}; CORRADE_COMPARE(profiler.maxFrameCount(), 4); /* MSVC 2015 needs the {} */ - for(auto value: {GLFrameProfiler::Value::CpuDuration, - GLFrameProfiler::Value::GpuDuration, + for(auto value: {FrameProfilerGL::Value::CpuDuration, + FrameProfilerGL::Value::GpuDuration, #ifndef MAGNUM_TARGET_GLES - GLFrameProfiler::Value::VertexFetchRatio, - GLFrameProfiler::Value::PrimitiveClipRatio + FrameProfilerGL::Value::VertexFetchRatio, + FrameProfilerGL::Value::PrimitiveClipRatio #endif }) { if(data.values & value) @@ -153,8 +153,8 @@ void FrameProfilerGLTest::test() { /* The GPU time should not be a total zero. Can't test upper bound because (especially on overloaded CIs) it all takes a magnitude more than expected. */ - if(data.values & GLFrameProfiler::Value::GpuDuration) { - CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::GpuDuration)); + if(data.values & FrameProfilerGL::Value::GpuDuration) { + CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::GpuDuration)); CORRADE_COMPARE_AS(profiler.gpuDurationMean(), 100, TestSuite::Compare::Greater); } @@ -162,24 +162,24 @@ void FrameProfilerGLTest::test() { /* 3/4 frames took 1 ms, the ideal average is 0.75 ms. Can't test upper bound because (especially on overloaded CIs) it all takes a magnitude more than expected. */ - if(data.values & GLFrameProfiler::Value::CpuDuration) { - CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration)); + if(data.values & FrameProfilerGL::Value::CpuDuration) { + CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration)); CORRADE_COMPARE_AS(profiler.cpuDurationMean(), 0.70*1000*1000, TestSuite::Compare::GreaterOrEqual); } #ifndef MAGNUM_TARGET_GLES /* 24 unique vertices in 12 triangles, ideal ratio is 24/36 */ - if(data.values & GLFrameProfiler::Value::VertexFetchRatio) { - CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::VertexFetchRatio)); + if(data.values & FrameProfilerGL::Value::VertexFetchRatio) { + CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::VertexFetchRatio)); CORRADE_COMPARE_WITH(profiler.vertexFetchRatioMean()/1000, 0.6667, TestSuite::Compare::around(0.1)); } /* We use a default transformation, which means the whole cube should be visible, nothing clipped */ - if(data.values & GLFrameProfiler::Value::PrimitiveClipRatio) { - CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::PrimitiveClipRatio)); + if(data.values & FrameProfilerGL::Value::PrimitiveClipRatio) { + CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::PrimitiveClipRatio)); CORRADE_COMPARE(profiler.primitiveClipRatioMean()/1000, 0.0); } #endif @@ -190,7 +190,7 @@ void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() { if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported."); - GLFrameProfiler profiler{GLFrameProfiler::Value::VertexFetchRatio, 4}; + FrameProfilerGL profiler{FrameProfilerGL::Value::VertexFetchRatio, 4}; profiler.beginFrame(); profiler.endFrame(); @@ -208,7 +208,7 @@ void FrameProfilerGLTest::vertexFetchRatioDivisionByZero() { /* No draws happened, so the ratio should be 0 (and not crashing with a division by zero) */ - CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::VertexFetchRatio)); + CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::VertexFetchRatio)); CORRADE_COMPARE(profiler.vertexFetchRatioMean(), 0.0); } @@ -216,7 +216,7 @@ void FrameProfilerGLTest::primitiveClipRatioDivisionByZero() { if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::pipeline_statistics_query::string() << "is not supported."); - GLFrameProfiler profiler{GLFrameProfiler::Value::PrimitiveClipRatio, 4}; + FrameProfilerGL profiler{FrameProfilerGL::Value::PrimitiveClipRatio, 4}; profiler.beginFrame(); profiler.endFrame(); @@ -234,7 +234,7 @@ void FrameProfilerGLTest::primitiveClipRatioDivisionByZero() { /* No draws happened, so the ratio should be 0 (and not crashing with a division by zero) */ - CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::PrimitiveClipRatio)); + CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::PrimitiveClipRatio)); CORRADE_COMPARE(profiler.primitiveClipRatioMean(), 0.0); } #endif diff --git a/src/Magnum/DebugTools/Test/FrameProfilerTest.cpp b/src/Magnum/DebugTools/Test/FrameProfilerTest.cpp index 16a65fc83..7f0b79aba 100644 --- a/src/Magnum/DebugTools/Test/FrameProfilerTest.cpp +++ b/src/Magnum/DebugTools/Test/FrameProfilerTest.cpp @@ -98,14 +98,14 @@ struct { #ifdef MAGNUM_TARGET_GL struct { const char* name; - GLFrameProfiler::Values values; + FrameProfilerGL::Values values; UnsignedInt measurementCount; UnsignedInt measurementDelay; } GLData[]{ {"empty", {}, 0, 1}, - {"frame time", GLFrameProfiler::Value::FrameTime, 1, 2}, - {"cpu duration", GLFrameProfiler::Value::CpuDuration, 1, 1}, - {"frame time + cpu duration", GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::CpuDuration, 2, 2} + {"frame time", FrameProfilerGL::Value::FrameTime, 1, 2}, + {"cpu duration", FrameProfilerGL::Value::CpuDuration, 1, 1}, + {"frame time + cpu duration", FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::CpuDuration, 2, 2} }; #endif @@ -1114,16 +1114,16 @@ void FrameProfilerTest::gl() { setTestCaseDescription(data.name); /* Test that we use the right state pointers to survive a move */ - Containers::Pointer profiler_{InPlaceInit, data.values, 4u}; - GLFrameProfiler profiler = std::move(*profiler_); + Containers::Pointer profiler_{InPlaceInit, data.values, 4u}; + FrameProfilerGL profiler = std::move(*profiler_); profiler_ = nullptr; CORRADE_COMPARE(profiler.values(), data.values); CORRADE_COMPARE(profiler.maxFrameCount(), 4); CORRADE_COMPARE(profiler.measurementCount(), data.measurementCount); /* MSVC 2015 needs the {} */ - for(auto value: {GLFrameProfiler::Value::CpuDuration, - GLFrameProfiler::Value::FrameTime}) { + for(auto value: {FrameProfilerGL::Value::CpuDuration, + FrameProfilerGL::Value::FrameTime}) { if(data.values & value) CORRADE_VERIFY(!profiler.isMeasurementAvailable(value)); } @@ -1152,8 +1152,8 @@ void FrameProfilerTest::gl() { bound because (especially on overloaded CIs) it all takes a magnitude more than expected. Emscripten builds have it as low as 0.5, account for that. */ - if(data.values & GLFrameProfiler::Value::CpuDuration) { - CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration)); + if(data.values & FrameProfilerGL::Value::CpuDuration) { + CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration)); CORRADE_COMPARE_AS(profiler.cpuDurationMean(), 0.50*1000*1000, TestSuite::Compare::GreaterOrEqual); } @@ -1161,8 +1161,8 @@ void FrameProfilerTest::gl() { /* 3/4 frames took 1 ms, and one 10 ms, the ideal average is 3.25 ms. Can't test upper bound because (especially on overloaded CIs) it all takes a magnitude more than expected. */ - if(data.values & GLFrameProfiler::Value::FrameTime) { - CORRADE_VERIFY(profiler.isMeasurementAvailable(GLFrameProfiler::Value::FrameTime)); + if(data.values & FrameProfilerGL::Value::FrameTime) { + CORRADE_VERIFY(profiler.isMeasurementAvailable(FrameProfilerGL::Value::FrameTime)); CORRADE_COMPARE_AS(profiler.frameTimeMean(), 3.20*1000*1000, TestSuite::Compare::GreaterOrEqual); } @@ -1175,19 +1175,19 @@ void FrameProfilerTest::glNotEnabled() { CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); #endif - GLFrameProfiler profiler{{}, 5}; + FrameProfilerGL profiler{{}, 5}; std::ostringstream out; Error redirectError{&out}; - profiler.isMeasurementAvailable(GLFrameProfiler::Value::CpuDuration); + profiler.isMeasurementAvailable(FrameProfilerGL::Value::CpuDuration); profiler.frameTimeMean(); profiler.cpuDurationMean(); profiler.gpuDurationMean(); CORRADE_COMPARE(out.str(), - "DebugTools::GLFrameProfiler::isMeasurementAvailable(): DebugTools::GLFrameProfiler::Value::CpuDuration not enabled\n" - "DebugTools::GLFrameProfiler::frameTimeMean(): not enabled\n" - "DebugTools::GLFrameProfiler::cpuDurationMean(): not enabled\n" - "DebugTools::GLFrameProfiler::gpuDurationMean(): not enabled\n"); + "DebugTools::FrameProfilerGL::isMeasurementAvailable(): DebugTools::FrameProfilerGL::Value::CpuDuration not enabled\n" + "DebugTools::FrameProfilerGL::frameTimeMean(): not enabled\n" + "DebugTools::FrameProfilerGL::cpuDurationMean(): not enabled\n" + "DebugTools::FrameProfilerGL::gpuDurationMean(): not enabled\n"); } #endif @@ -1202,47 +1202,47 @@ void FrameProfilerTest::debugUnits() { void FrameProfilerTest::debugGLValue() { std::ostringstream out; - Debug{&out} << GLFrameProfiler::Value::GpuDuration << GLFrameProfiler::Value(0xfff0); - CORRADE_COMPARE(out.str(), "DebugTools::GLFrameProfiler::Value::GpuDuration DebugTools::GLFrameProfiler::Value(0xfff0)\n"); + Debug{&out} << FrameProfilerGL::Value::GpuDuration << FrameProfilerGL::Value(0xfff0); + CORRADE_COMPARE(out.str(), "DebugTools::FrameProfilerGL::Value::GpuDuration DebugTools::FrameProfilerGL::Value(0xfff0)\n"); } void FrameProfilerTest::debugGLValues() { std::ostringstream out; - Debug{&out} << (GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::FrameTime) << GLFrameProfiler::Values{}; - CORRADE_COMPARE(out.str(), "DebugTools::GLFrameProfiler::Value::FrameTime|DebugTools::GLFrameProfiler::Value::CpuDuration DebugTools::GLFrameProfiler::Values{}\n"); + Debug{&out} << (FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::FrameTime) << FrameProfilerGL::Values{}; + CORRADE_COMPARE(out.str(), "DebugTools::FrameProfilerGL::Value::FrameTime|DebugTools::FrameProfilerGL::Value::CpuDuration DebugTools::FrameProfilerGL::Values{}\n"); } void FrameProfilerTest::configurationGLValue() { Utility::ConfigurationGroup c; - c.setValue("value", GLFrameProfiler::Value::GpuDuration); + c.setValue("value", FrameProfilerGL::Value::GpuDuration); CORRADE_COMPARE(c.value("value"), "GpuDuration"); - CORRADE_COMPARE(c.value("value"), GLFrameProfiler::Value::GpuDuration); + CORRADE_COMPARE(c.value("value"), FrameProfilerGL::Value::GpuDuration); - c.setValue("zero", GLFrameProfiler::Value{}); + c.setValue("zero", FrameProfilerGL::Value{}); CORRADE_COMPARE(c.value("zero"), ""); - CORRADE_COMPARE(c.value("zero"), GLFrameProfiler::Value{}); + CORRADE_COMPARE(c.value("zero"), FrameProfilerGL::Value{}); - c.setValue("invalid", GLFrameProfiler::Value(0xdead)); + c.setValue("invalid", FrameProfilerGL::Value(0xdead)); CORRADE_COMPARE(c.value("invalid"), ""); - CORRADE_COMPARE(c.value("invalid"), GLFrameProfiler::Value{}); + CORRADE_COMPARE(c.value("invalid"), FrameProfilerGL::Value{}); } void FrameProfilerTest::configurationGLValues() { Utility::ConfigurationGroup c; - c.setValue("value", GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration); + c.setValue("value", FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration); CORRADE_COMPARE(c.value("value"), "FrameTime CpuDuration GpuDuration"); - CORRADE_COMPARE(c.value("value"), GLFrameProfiler::Value::FrameTime|GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration); + CORRADE_COMPARE(c.value("value"), FrameProfilerGL::Value::FrameTime|FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration); - c.setValue("empty", GLFrameProfiler::Values{}); + c.setValue("empty", FrameProfilerGL::Values{}); CORRADE_COMPARE(c.value("empty"), ""); - CORRADE_COMPARE(c.value("empty"), GLFrameProfiler::Values{}); + CORRADE_COMPARE(c.value("empty"), FrameProfilerGL::Values{}); - c.setValue("invalid", GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration|GLFrameProfiler::Value(0xff00)); + c.setValue("invalid", FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration|FrameProfilerGL::Value(0xff00)); CORRADE_COMPARE(c.value("invalid"), "CpuDuration GpuDuration"); - CORRADE_COMPARE(c.value("invalid"), GLFrameProfiler::Value::CpuDuration|GLFrameProfiler::Value::GpuDuration); + CORRADE_COMPARE(c.value("invalid"), FrameProfilerGL::Value::CpuDuration|FrameProfilerGL::Value::GpuDuration); } #endif From 2066d82ea495bdc2bbabf848289b98d450a1de7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Apr 2021 16:34:45 +0200 Subject: [PATCH 143/161] Shaders: suffix all existing shaders with GL. To make room for Vulkan shaders. Also renaming the headers, of course everything is still aliased to the old names (and marked as deprecated). --- doc/changelog-old.dox | 35 +- doc/changelog.dox | 234 ++-- doc/developers.dox | 4 +- doc/generated/primitives.cpp | 28 +- doc/generated/shaders.cpp | 40 +- doc/namespaces.dox | 14 +- doc/shaders.dox | 54 +- doc/snippets/CMakeLists.txt | 2 +- doc/snippets/MagnumGL.cpp | 26 +- doc/snippets/MagnumSceneGraph-gl.cpp | 12 +- ...MagnumShaders.cpp => MagnumShaders-gl.cpp} | 258 ++-- doc/snippets/MagnumText.cpp | 4 +- doc/snippets/MagnumTrade.cpp | 8 +- src/Magnum/DebugTools/ForceRenderer.cpp | 8 +- src/Magnum/DebugTools/ForceRenderer.h | 2 +- src/Magnum/DebugTools/ObjectRenderer.cpp | 6 +- src/Magnum/DebugTools/ObjectRenderer.h | 2 +- .../DebugTools/Test/FrameProfilerGLTest.cpp | 4 +- src/Magnum/GL/Framebuffer.h | 4 +- src/Magnum/GL/Mesh.h | 2 +- src/Magnum/GL/Renderer.h | 7 +- src/Magnum/Math/Vector.h | 5 + src/Magnum/MeshTools/Compile.cpp | 16 +- src/Magnum/MeshTools/Compile.h | 39 +- src/Magnum/MeshTools/Test/CompileGLTest.cpp | 54 +- src/Magnum/SceneGraph/Drawable.h | 4 +- src/Magnum/Shaders/AbstractVector.h | 106 +- ...bstractVector.cpp => AbstractVectorGL.cpp} | 8 +- src/Magnum/Shaders/AbstractVectorGL.h | 126 ++ src/Magnum/Shaders/CMakeLists.txt | 48 +- src/Magnum/Shaders/DistanceFieldVector.h | 253 +--- ...ldVector.cpp => DistanceFieldVectorGL.cpp} | 44 +- src/Magnum/Shaders/DistanceFieldVectorGL.h | 275 +++++ src/Magnum/Shaders/Flat.h | 517 +------- src/Magnum/Shaders/{Flat.cpp => FlatGL.cpp} | 60 +- src/Magnum/Shaders/FlatGL.h | 539 +++++++++ src/Magnum/Shaders/Generic.h | 470 +------- src/Magnum/Shaders/GenericGL.h | 521 ++++++++ .../CreateCompatibilityShader.h | 2 +- src/Magnum/Shaders/MeshVisualizer.h | 1030 +--------------- ...eshVisualizer.cpp => MeshVisualizerGL.cpp} | 136 +-- src/Magnum/Shaders/MeshVisualizerGL.h | 1038 ++++++++++++++++ src/Magnum/Shaders/Phong.h | 1029 +--------------- src/Magnum/Shaders/{Phong.cpp => PhongGL.cpp} | 150 +-- src/Magnum/Shaders/PhongGL.h | 1052 +++++++++++++++++ src/Magnum/Shaders/Shaders.h | 68 +- src/Magnum/Shaders/Test/CMakeLists.txt | 28 +- .../Test/DistanceFieldVectorGLTest.cpp | 34 +- ...est.cpp => DistanceFieldVectorGL_Test.cpp} | 48 +- src/Magnum/Shaders/Test/FlatGLTest.cpp | 158 +-- .../Test/{FlatTest.cpp => FlatGL_Test.cpp} | 60 +- src/Magnum/Shaders/Test/GenericGL_Test.cpp | 118 ++ src/Magnum/Shaders/Test/GenericTest.cpp | 116 -- .../Shaders/Test/MeshVisualizerGLTest.cpp | 430 +++---- .../Shaders/Test/MeshVisualizerGL_Test.cpp | 145 +++ .../Shaders/Test/MeshVisualizerTest.cpp | 143 --- src/Magnum/Shaders/Test/PhongGLTest.cpp | 250 ++-- .../Test/{PhongTest.cpp => PhongGL_Test.cpp} | 56 +- src/Magnum/Shaders/Test/VectorGLTest.cpp | 34 +- .../{VectorTest.cpp => VectorGL_Test.cpp} | 48 +- src/Magnum/Shaders/Test/VertexColorGLTest.cpp | 26 +- ...exColorTest.cpp => VertexColorGL_Test.cpp} | 32 +- src/Magnum/Shaders/Vector.h | 220 +--- .../Shaders/{Vector.cpp => VectorGL.cpp} | 40 +- src/Magnum/Shaders/VectorGL.h | 242 ++++ src/Magnum/Shaders/VertexColor.h | 152 +-- .../{VertexColor.cpp => VertexColorGL.cpp} | 14 +- src/Magnum/Shaders/VertexColorGL.h | 172 +++ .../{resources.conf => resources-gl.conf} | 2 +- src/Magnum/Text/Renderer.cpp | 12 +- src/Magnum/Text/Renderer.h | 4 +- src/Magnum/TextureTools/DistanceField.h | 2 +- .../TextureTools/distancefieldconverter.cpp | 2 +- src/Magnum/Trade/MeshData.h | 16 +- 74 files changed, 5821 insertions(+), 5127 deletions(-) rename doc/snippets/{MagnumShaders.cpp => MagnumShaders-gl.cpp} (70%) rename src/Magnum/Shaders/{AbstractVector.cpp => AbstractVectorGL.cpp} (83%) create mode 100644 src/Magnum/Shaders/AbstractVectorGL.h rename src/Magnum/Shaders/{DistanceFieldVector.cpp => DistanceFieldVectorGL.cpp} (75%) create mode 100644 src/Magnum/Shaders/DistanceFieldVectorGL.h rename src/Magnum/Shaders/{Flat.cpp => FlatGL.cpp} (78%) create mode 100644 src/Magnum/Shaders/FlatGL.h create mode 100644 src/Magnum/Shaders/GenericGL.h rename src/Magnum/Shaders/{MeshVisualizer.cpp => MeshVisualizerGL.cpp} (83%) create mode 100644 src/Magnum/Shaders/MeshVisualizerGL.h rename src/Magnum/Shaders/{Phong.cpp => PhongGL.cpp} (75%) create mode 100644 src/Magnum/Shaders/PhongGL.h rename src/Magnum/Shaders/Test/{DistanceFieldVectorTest.cpp => DistanceFieldVectorGL_Test.cpp} (51%) rename src/Magnum/Shaders/Test/{FlatTest.cpp => FlatGL_Test.cpp} (53%) create mode 100644 src/Magnum/Shaders/Test/GenericGL_Test.cpp create mode 100644 src/Magnum/Shaders/Test/MeshVisualizerGL_Test.cpp delete mode 100644 src/Magnum/Shaders/Test/MeshVisualizerTest.cpp rename src/Magnum/Shaders/Test/{PhongTest.cpp => PhongGL_Test.cpp} (54%) rename src/Magnum/Shaders/Test/{VectorTest.cpp => VectorGL_Test.cpp} (54%) rename src/Magnum/Shaders/Test/{VertexColorTest.cpp => VertexColorGL_Test.cpp} (63%) rename src/Magnum/Shaders/{Vector.cpp => VectorGL.cpp} (78%) create mode 100644 src/Magnum/Shaders/VectorGL.h rename src/Magnum/Shaders/{VertexColor.cpp => VertexColorGL.cpp} (89%) create mode 100644 src/Magnum/Shaders/VertexColorGL.h rename src/Magnum/Shaders/{resources.conf => resources-gl.conf} (95%) diff --git a/doc/changelog-old.dox b/doc/changelog-old.dox index 096538b09..1c549b7bd 100644 --- a/doc/changelog-old.dox +++ b/doc/changelog-old.dox @@ -316,10 +316,12 @@ Released 2018-05-01, tagged as are deprecated because texture binding (a global state) is confused there with uniform setup (a shader-local state). That can lead to accidental state mismatches where a texture is forgotten to be rebound. Use - @ref Shaders::AbstractVector::bindVectorTexture() "Shaders::*Vector::bindVectorTexture()", - @ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(), - @ref Shaders::Phong::bindDiffuseTexture(), @ref Shaders::Phong::bindSpecularTexture() - and @ref Shaders::Phong::bindTextures() instead. + @cpp Shaders::*Vector::bindVectorTexture() @ce, + @cpp Shaders::Flat::bindTexture() @ce, + @cpp Shaders::Phong::bindAmbientTexture() @ce, + @cpp Shaders::Phong::bindDiffuseTexture() @ce, + @cpp Shaders::Phong::bindSpecularTexture() @ce + and @cpp Shaders::Phong::bindTextures() @ce instead. @subsection changelog-2018-04-compatibility Potential compatibility breakages, removed APIs @@ -919,9 +921,10 @@ a high-level overview. @subsubsection changelog-2018-02-changes-shaders Shaders library -- @ref Shaders::Flat now sets default color to white only in textured version -- @ref Shaders::Phong gained the ability to have both color and texture -- @ref Shaders::Phong is now able to do alpha-masking (see +- @cpp Shaders::Flat @ce now sets default color to white only in textured + version +- @cpp Shaders::Phong @ce gained the ability to have both color and texture +- @cpp Shaders::Phong @ce is now able to do alpha-masking (see [mosra/magnum#112](https://github.com/mosra/magnum/issues/112), [mosra/magnum-examples#29](https://github.com/mosra/magnum-examples/issues/29)) @@ -1307,8 +1310,8 @@ for a high-level overview. - Fixed @cpp TextureTools::distanceField() @ce to work in GLSL < 4.20 (see [mosra/magnum#62](https://github.com/mosra/magnum/issues/62)). -- Fixed @ref Shaders::MeshVisualizer to work in GLSL ES. -- Fixed @ref Shaders::Vector "Shaders::*Vector" on Intel GPUs. +- Fixed @cpp Shaders::MeshVisualizer @ce to work in GLSL ES. +- Fixed @cpp Shaders::*Vector @ce on Intel GPUs. - Fixed assertion on contexts without default framebuffer (see [mosra/magnum#93](https://github.com/mosra/magnum/issues/93)). - Fixed cases where shader would use extension that is not advertised by the @@ -1528,8 +1531,8 @@ for a high-level overview. - Fixed usage with OpenGL ES 3.1 contexts (it complained about invalid version) -- Fixed compilation of Shaders::MeshVisualizer under WebGL and with ANGLE, - see [mosra/magnum#56](https://github.com/mosra/magnum/issues/56) +- Fixed compilation of @cpp Shaders::MeshVisualizer @ce under WebGL and with + ANGLE, see [mosra/magnum#56](https://github.com/mosra/magnum/issues/56) - Fixed various build issues on Mac OS X, see [mosra/magnum#51](https://github.com/mosra/magnum/issues/51) and [mosra/magnum#54](https://github.com/mosra/magnum/issues/54) @@ -1672,10 +1675,10 @@ No dependency changes in this release. preserve source compatibility with other application classes. - @ref SceneGraph::Drawable::drawables() function as a non-ambiguous alternative to @cpp group() @ce -- Ability to specify background color color in @ref Shaders::Vector, +- Ability to specify background color color in @cpp Shaders::Vector @ce, allowing it to use without blending enabled (fully transparent black was used previously) -- New @ref Shaders::Generic class with common definitions, so you can +- New @cpp Shaders::Generic @ce class with common definitions, so you can configure mesh for the generic shader and render it with any other compatible shader - Convenience @cpp hasNormals() @ce, @cpp hasTextureCoords2D() @ce functions @@ -1707,7 +1710,7 @@ No dependency changes in this release. - Implementation of @ref Platform::Sdl2Application::viewportEvent() "Platform::*Application::viewportEvent()" is not required anymore, because in many cases the application doesn't need to react to window resize events at all -- Textured @ref Shaders::Flat now multiplies texture with the specified +- Textured @cpp Shaders::Flat @ce now multiplies texture with the specified color instead of ignoring it. See also [mosra/magnum#34](https://github.com/mosra/magnum/issues/34) - All deprecated functions and types are now emitting compiler warnings to encourage updating the code @@ -1724,7 +1727,7 @@ No dependency changes in this release. - @cpp Mesh::addVertexBuffer() @ce now properly computes offsets for matrix attributes - Taking index buffer offset into account in @cpp MeshView @ce class -- Fixed various issues with textured @ref Shaders::Flat shader (actually +- Fixed various issues with textured @cpp Shaders::Flat @ce shader (actually the textured version was not working at all) - Various OS X-related fixes in @ref Shaders library. See also [mosra/magnum#27](https://github.com/mosra/magnum/issues/27). @@ -1840,7 +1843,7 @@ for a high-level overview. - New translation-only transformation in @ref SceneGraph supporting also purely integral coordinates, useful e.g. for UI or 2D platformers. - Detailed collision queries and new `InvertedSphere` shape in Shapes library -- Texture support in @ref Shaders::Flat +- Texture support in @cpp Shaders::Flat @ce - Mouse button queries in @ref Platform::Sdl2Application::MouseMoveEvent "Platform::*Application::MouseMoveEvent" @subsection changelog-2013-10-changes Changes diff --git a/doc/changelog.dox b/doc/changelog.dox index 1794ddd02..f6b54981e 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -142,13 +142,14 @@ See also: @subsubsection changelog-latest-new-shaders Shaders library -- Added @ref Shaders::Phong::setNormalTextureScale(), consuming the recently - added @ref Trade::MaterialAttribute::NormalTextureScale material attribute -- @ref Shaders::Phong was reworked to support directional and +- Added @ref Shaders::PhongGL::setNormalTextureScale(), consuming the + recently added @ref Trade::MaterialAttribute::NormalTextureScale material + attribute +- @ref Shaders::PhongGL was reworked to support directional and range-attenuated point lights to follow the additions to @ref Trade::LightData -- Added @ref Shaders::Phong::setLightSpecularColors() for better control over - speculat highlights +- Added @ref Shaders::PhongGL::setLightSpecularColors() for better control + over specular highlights @subsubsection changelog-latest-new-shadertools ShaderTools library @@ -293,13 +294,13 @@ See also: @subsubsection changelog-latest-changes-shaders Shaders library -- In the original implementation of normal mapping in @ref Shaders::Phong, +- In the original implementation of normal mapping in @ref Shaders::PhongGL, there shader didn't provide a way to supply bitangent direction, forcing users to patch normal maps. This is now possible using newly added - @ref Shaders::Phong::Tangent4, @ref Shaders::Phong::Bitangent attributes - and a @ref Shaders::Phong::Flag::Bitangent flag, implementing support for - both four-component tangents (used by glTF, for example) and separate - tangent and bitangent direction (used by Assimp). + @ref Shaders::PhongGL::Tangent4, @ref Shaders::PhongGL::Bitangent + attributes and a @ref Shaders::PhongGL::Flag::Bitangent flag, implementing + support for both four-component tangents (used by glTF, for example) and + separate tangent and bitangent direction (used by Assimp). @subsubsection changelog-latest-changes-trade Trade library @@ -383,10 +384,10 @@ See also: - For meshes with multiple sets of vertex attributes (such as texture coordinates), @ref MeshTools::compile() should be using only the first set but it wasn't. -- @ref Shaders::Phong was normalizing light direction in vertex shader, +- @ref Shaders::PhongGL was normalizing light direction in vertex shader, causing the fragment-interpolated direction being incorrect with visible artifacts on long polygons under low light angle -- @ref Shaders::Phong wasn't normalizing normals coming from normal textures, +- @ref Shaders::PhongGL wasn't normalizing normals coming from normal textures, which may have caused slight artifacts due to limited precision of 8-bit pixel formats - @ref Text::AbstractFontConverter::exportFontToData() and @@ -441,19 +442,32 @@ See also: @ref DebugTools::FrameProfilerGL. The new name plays better with IDE autocompletion and makes the GL-specific class appear next to the API-independent base in alphabetically sorted lists. -- @ref Shaders::Phong::setLightPositions() and - @ref Shaders::Phong::setLightPosition() taking three-component vectors are - deprecated in favor of variants taking four-component vectors, where the +- @cpp Shaders::AbstractVector @ce, @cpp Shaders::DistanceFieldVector @ce, + @cpp Shaders::Flat @ce, @cpp Shaders::Generic @ce, + @cpp Shaders::MeshVisualizer2D @ce, @cpp Shaders::MeshVisualizer3D @ce, + @cpp Shaders::Phong @ce, @cpp Shaders::Vector @ce, + @cpp Shaders::VertexColor @ce and related 2D/3D typedefs are deprecated in + favor of @ref Shaders::AbstractVectorGL, + @ref Shaders::DistanceFieldVectorGL, @ref Shaders::FlatGL, + @ref Shaders::GenericGL, @ref Shaders::MeshVisualizerGL2D, + @ref Shaders::MeshVisualizerGL3D, @ref Shaders::PhongGL, + @ref Shaders::VectorGL, @ref Shaders::VertexColorGL and correspondingly + renamed typedefs to make room for Vulkan shaders and functionality shared + between OpenGL and Vulkan implementation such as uniform buffer layout + definitions +- @ref Shaders::PhongGL::setLightPositions() and + @ref Shaders::PhongGL::setLightPosition() taking three-component vectors + are deprecated in favor of variants taking four-component vectors, where the last component distinguishes between directional and point lights -- @cpp Shaders::Phong::setLightPosition(const Vector3&) @ce is deprecated in - favor of @ref Shaders::Phong::setLightPositions() with a single item --- +- @cpp Shaders::PhongGL::setLightPosition(const Vector3&) @ce is deprecated + in favor of @ref Shaders::PhongGL::setLightPositions() with a single item --- it's short enough to not warrant the existence of a dedicated overload -- @ref Shaders::Phong::setLightColors() and - @ref Shaders::Phong::setLightColor() taking four-component colors are +- @ref Shaders::PhongGL::setLightColors() and + @ref Shaders::PhongGL::setLightColor() taking four-component colors are deprecated in favor of variants taking just three-component colors, as the alpha had no meaningful use anyway. -- @cpp Shaders::Phong::setLightColor(const Magnum::Color4&) @ce is deprecated - in favor of @ref Shaders::Phong::setLightColors() with a single item --- +- @cpp Shaders::PhongGL::setLightColor(const Magnum::Color4&) @ce is deprecated + in favor of @ref Shaders::PhongGL::setLightColors() with a single item --- it's short enough to not warrant the existence of a dedicated overload - @cpp Trade::AbstractMaterialData @ce as well as its containing header `Magnum/Trade/AbstractMaterialData.h` is now a deprecated alias to the new @@ -570,9 +584,9 @@ See also: function instead. - `Platform::Sdl2Application::Configuration::WindowFlags::AllowHighDpi`, had no effect anymore - - `Shaders::Generic::Color` and `Shaders::VertexColor::Color`, use - @ref Shaders::VertexColor::Color3 or @ref Shaders::VertexColor::Color4 - instead + - `Shaders::GenericGL::Color` and `Shaders::VertexColorGL::Color`, use + @ref Shaders::VertexColorGL::Color3 or + @ref Shaders::VertexColorGL::Color4 instead - @ref Trade::CameraData constructor not taking an explicit type enum, use @ref Trade::CameraData::CameraData(CameraType, Rad, Float, Float, Float, const void*) instead @@ -619,7 +633,7 @@ See also: made both @cpp nullptr @ce even before the object/feature destructors were called and so it's assumed no code relied on such behavior, nevertheless it's a subtle change worth mentioning. -- Due to the rework of @ref Shaders::Phong to support directional and +- Due to the rework of @ref Shaders::PhongGL to support directional and attenuated point lights, the original behavior of unattenuated point lights isn't available anymore. For backwards compatibility, light positions supplied through three-component vectors are now represented as directional @@ -884,21 +898,22 @@ Released 2020-06-27, tagged as @subsubsection changelog-2020-06-new-shaders Shaders library -- New @ref Shaders::MeshVisualizer2D for 2D mesh visualization -- Tangent space visualization in @ref Shaders::MeshVisualizer3D +- New @cpp Shaders::MeshVisualizer2D @ce for 2D mesh visualization +- Tangent space visualization in @cpp Shaders::MeshVisualizer3D @ce - Object, vertex and primitive ID visualization in - @ref Shaders::MeshVisualizer2D and @ref Shaders::MeshVisualizer3D -- Texture coordinate transformation in @ref Shaders::DistanceFieldVector, - @ref Shaders::Flat, @ref Shaders::Phong and @ref Shaders::Vector -- Ability to render per-instance / per-vertex object ID in @ref Shaders::Flat - and @ref Shaders::Phong, in addition to uniform object ID + @cpp Shaders::MeshVisualizer2D @ce and @cpp Shaders::MeshVisualizer3D @ce +- Texture coordinate transformation in @cpp Shaders::DistanceFieldVector @ce, + @cpp Shaders::Flat @ce, @cpp Shaders::Phong @ce and @cpp Shaders::Vector @ce +- Ability to render per-instance / per-vertex object ID in + @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce, in addition to uniform + object ID - New attribute definitions and an location allocation scheme in - @ref Shaders::Generic --- @ref Shaders::Generic::Tangent4, - @ref Shaders::Generic::Bitangent, @ref Shaders::Generic::ObjectId plus - @ref Shaders::Generic::TransformationMatrix, - @ref Shaders::Generic::NormalMatrix and - @ref Shaders::Generic::TextureOffset for instancing -- Instancing in @ref Shaders::Flat and @ref Shaders::Phong + @cpp Shaders::Generic @ce --- @cpp Shaders::Generic::Tangent4 @ce, + @cpp Shaders::Generic::Bitangent @ce, @cpp Shaders::Generic::ObjectId @ce + plus @cpp Shaders::Generic::TransformationMatrix @ce, + @cpp Shaders::Generic::NormalMatrix @ce and + @cpp Shaders::Generic::TextureOffset @ce for instancing +- Instancing in @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce @subsubsection changelog-2020-06-new-trade Trade library @@ -966,10 +981,10 @@ Released 2020-06-27, tagged as `Magnum/version.h` header. This header is not included by any other header to avoid trigerring a full rebuild when Git commit changes. If Git is not found, only the first two defines are present. -- @ref Shaders::MeshVisualizer3D::Flag::Wireframe now implicitly enables - @ref Shaders::MeshVisualizer3D::Flag::NoGeometryShader also on WebGL in +- @cpp Shaders::MeshVisualizer3D::Flag::Wireframe @ce now implicitly enables + @cpp Shaders::MeshVisualizer3D::Flag::NoGeometryShader @ce also on WebGL in addition to ES2, since this platform doesn't have a possibility to have - geometry shaders either. Same is done for @ref Shaders::MeshVisualizer2D. + geometry shaders either. Same is done for @cpp Shaders::MeshVisualizer2D @ce. @subsubsection changelog-2020-06-changes-audio Audio library @@ -1206,9 +1221,9 @@ Released 2020-06-27, tagged as - @ref Resource was unnecessarily querying the @ref ResourceManager for updated data even in cases where no resource update was done since last check -- For a @ref Shaders::Phong with zero lights, alpha mask default value was - incorrectly @cpp 0.0f @ce instead of @cpp 0.5f @ce on OpenGL ES -- @ref Shaders::MeshVisualizer3D accidentally didn't enable +- For a @cpp Shaders::Phong @ce with zero lights, alpha mask default value + was incorrectly @cpp 0.0f @ce instead of @cpp 0.5f @ce on OpenGL ES +- @cpp Shaders::MeshVisualizer3D @ce accidentally didn't enable @glsl noperspective @ce interpolation on desktop, resulting in minor wireframe rendering artifacts - @ref Math::angle() got fixed to not produce NaN results for vectors, @@ -1310,14 +1325,14 @@ Released 2020-06-27, tagged as @ref Primitives::GridFlag::TextureCoordinates and @ref Primitives::GridFlag::Normals for naming consistency - @cpp Shaders::MeshVisualizer @ce is deprecated as the shader can now handle - both 2D and 3D, use @ref Shaders::MeshVisualizer3D instead -- Default constructor of @ref Shaders::MeshVisualizer3D is deprecated, you're - now required to enable at least one visualization feature when constructing - it + both 2D and 3D, use @cpp Shaders::MeshVisualizer3D @ce instead +- Default constructor of @cpp Shaders::MeshVisualizer3D @ce is deprecated, + you're now required to enable at least one visualization feature when + constructing it - @cpp Shaders::MeshVisualizer::setTransformationProjectionMatrix() @ce is deprecated on the 3D variant, use separate - @ref Shaders::MeshVisualizer3D::setTransformationMatrix() and - @ref Shaders::MeshVisualizer3D::setProjectionMatrix() instead + @cpp Shaders::MeshVisualizer3D::setTransformationMatrix() @ce and + @cpp Shaders::MeshVisualizer3D::setProjectionMatrix() @ce instead - Mutable access to @ref Trade::PhongMaterialData color and texture information is deprecated. This was mainly used to populate the contents in asset importers, but the class was redesigned and this is no longer @@ -1374,13 +1389,13 @@ Released 2020-06-27, tagged as for new attributes and use cases. This may break custom shaders if these rely on generic attribute definitions or are used together with @ref MeshTools::compile(). To avoid further breakages you're advised to - reuse the definitions from @ref Shaders::Generic (and propagating them to - shader code as well) instead of hardcoding the locations directly. - - @ref Shaders::Generic::Color3 / @ref Shaders::Generic::Color4 location - changed from @cpp 3 @ce to @cpp 2 @ce - - @ref Shaders::Generic::Normal location changed from @cpp 2 @ce to + reuse the definitions from @cpp Shaders::Generic @ce (and propagating them + to shader code as well) instead of hardcoding the locations directly. + - @cpp Shaders::Generic::Color3 @ce / @cpp Shaders::Generic::Color4 @ce + location changed from @cpp 3 @ce to @cpp 2 @ce + - @cpp Shaders::Generic::Normal @ce location changed from @cpp 2 @ce to @cpp 5 @ce - - @ref Shaders::Generic::Tangent location changed from @cpp 4 @ce to + - @cpp Shaders::Generic::Tangent @ce location changed from @cpp 4 @ce to @cpp 3 @ce - Removed remaining APIs deprecated in version 2018.04: - @cpp Audio::Buffer::Format @ce, use @ref Audio::BufferFormat instead @@ -1390,12 +1405,12 @@ Released 2020-06-27, tagged as @cpp Shaders::Phong::setDiffuseTexture() @ce, @cpp Shaders::Phong::setSpecularTexture() @ce and @cpp Shaders::Phong::setTextures() @ce, use - @ref Shaders::AbstractVector::bindVectorTexture() "Shaders::*Vector::bindVectorTexture()", - @ref Shaders::Flat::bindTexture(), - @ref Shaders::Phong::bindAmbientTexture(), - @ref Shaders::Phong::bindDiffuseTexture(), - @ref Shaders::Phong::bindSpecularTexture() and - @ref Shaders::Phong::bindTextures() instead + @cpp Shaders::*Vector::bindVectorTexture() @ce, + @cpp Shaders::Flat::bindTexture() @ce, + @cpp Shaders::Phong::bindAmbientTexture() @ce, + @cpp Shaders::Phong::bindDiffuseTexture() @ce, + @cpp Shaders::Phong::bindSpecularTexture() @ce and + @cpp Shaders::Phong::bindTextures() @ce instead - @ref MeshPrimitive is now four bytes instead of one, to allow wrapping implementation-specific values using @ref meshPrimitiveWrap() and @ref meshPrimitiveUnwrap() @@ -1415,7 +1430,7 @@ Released 2020-06-27, tagged as [mosra/magnum#394](https://github.com/mosra/magnum/pull/394), [mosra/magnum#418](https://github.com/mosra/magnum/pull/418), [mosra/magnum#424](https://github.com/mosra/magnum/pull/424)) -- @ref Shaders::Generic now shows the recommended way how to propagate +- @cpp Shaders::Generic @ce now shows the recommended way how to propagate generic attribute locations to custom shader code (see [mosra/magnum#443](https://github.com/mosra/magnum/issues/443)) @@ -1719,10 +1734,11 @@ Released 2019-10-24, tagged as @subsubsection changelog-2019-10-new-shaders Shaders library -- Normal texture support in @ref Shaders::Phong -- Added @ref Shaders::Generic3D::Tangent generic vertex attribute definition -- Object ID output in @ref Shaders::Flat and @ref Shaders::Phong -- Vertex color support in @ref Shaders::Flat and @ref Shaders::Phong +- Normal texture support in @cpp Shaders::Phong @ce +- Added @cpp Shaders::Generic3D::Tangent @ce generic vertex attribute + definition +- Object ID output in @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce +- Vertex color support in @cpp Shaders::Flat @ce and @cpp Shaders::Phong @ce @subsubsection changelog-2019-10-new-text Text library @@ -1867,12 +1883,12 @@ Released 2019-10-24, tagged as - All shaders now have rendering output tests, making them more robust for future additions and refactorings. See also [mosra/magnum#382](https://github.com/mosra/magnum/pull/382). -- @ref Shaders::Phong now clamps the specular factor to minimize artifacts +- @cpp Shaders::Phong @ce now clamps the specular factor to minimize artifacts when shininess is near zero -- @ref Shaders::Phong can now handle zero lights, in which case its output is - equivalent to @ref Shaders::Flat3D. See @ref Shaders-Phong-lights-zero for - more information. -- @ref Shaders::MeshVisualizer is fixed to work properly on Intel Windows +- @cpp Shaders::Phong @ce can now handle zero lights, in which case its output + is equivalent to @cpp Shaders::Flat3D @ce. See + @ref Shaders-PhongGL-lights-zero for more information. +- @cpp Shaders::MeshVisualizer @ce is fixed to work properly on Intel Windows drivers, adding a new @cpp "intel-windows-explicit-uniform-location-is-less-explicit-than-you-hoped" @ce workaround @@ -2081,8 +2097,8 @@ Released 2019-10-24, tagged as passing a freshly created @ref GL::Buffer to it was causing @ref GL::Renderer::Error::InvalidOperation on systems without @gl_extension{ARB,direct_state_access}. -- Fixed @ref Shaders::Vector and @ref Shaders::DistanceFieldVector to work - on iOS, which has only 8 texture binding slots in total (see +- Fixed @cpp Shaders::Vector @ce and @cpp Shaders::DistanceFieldVector @ce to + work on iOS, which has only 8 texture binding slots in total (see [mosra/magnum-examples#65](https://github.com/mosra/magnum-examples/issues/65) and [mosra/magnum#374](https://github.com/mosra/magnum/pull/374)) @@ -2247,10 +2263,10 @@ Released 2019-10-24, tagged as to indicate an invalid format, better catching accidentally forgotten initialization. Valid code shouldn't be affected by this change, but broken code that seemingly worked before might start throwing assertions now. -- @ref Shaders::MeshVisualizer now asserts if its wireframe-related setters - are called when the @ref Shaders::MeshVisualizer::Flag::Wireframe flag was - not set, consistently with other shaders. This might cause failures in code - that was calling them unnecessarily before. +- @cpp Shaders::MeshVisualizer @ce now asserts if its wireframe-related + setters are called when the @cpp Shaders::MeshVisualizer::Flag::Wireframe @ce + flag was not set, consistently with other shaders. This might cause + failures in code that was calling them unnecessarily before. @section changelog-2019-01 2019.01 @@ -2645,15 +2661,17 @@ Released 2018-10-23, tagged as @subsubsection changelog-2018-10-new-shaders Shaders library -- New dedicated @ref Shaders::VertexColor::Color3 and - @ref Shaders::VertexColor::Color4 attribute specifiers for more convenient - distinction between three- and four-component vertex color attribute. -- Support for multiple lights in @ref Shaders::Phong -- Classical alpha masking support in @ref Shaders::Flat and - @ref Shaders::Phong -- Debug output for the @ref Shaders::Flat::Flag / @ref Shaders::Flat::Flags, - @ref Shaders::MeshVisualizer::Flag / @ref Shaders::MeshVisualizer::Flags - and @ref Shaders::Phong::Flag / @ref Shaders::Phong::Flags enums / enum +- New dedicated @cpp Shaders::VertexColor::Color3 @ce and + @cpp Shaders::VertexColor::Color4 @ce attribute specifiers for more + convenient distinction between three- and four-component vertex color + attribute. +- Support for multiple lights in @cpp Shaders::Phong @ce +- Classical alpha masking support in @cpp Shaders::Flat @ce and + @cpp Shaders::Phong @ce +- Debug output for the @cpp Shaders::Flat::Flag @ce / + @cpp Shaders::Flat::Flags @ce, @cpp Shaders::MeshVisualizer::Flag @ce / + @cpp Shaders::MeshVisualizer::Flags @ce and + @cpp Shaders::Phong::Flag @ce / @cpp Shaders::Phong::Flags @ce enums / enum sets @subsubsection changelog-2018-10-new-trade Trade library @@ -2787,13 +2805,14 @@ Released 2018-10-23, tagged as - All shaders now have reasonable default values for uniforms in order to further simplify and remove friction from quick prototyping use cases -- @ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(), - @ref Shaders::Phong::bindDiffuseTexture(), - @ref Shaders::Phong::bindSpecularTexture() and - @ref Shaders::Phong::bindTextures() now assert that the shader was created - with the corresponding flag enabled to prevent accidental "black screen of - death" errors. -- Ambient color in untextured @ref Shaders::Phong now defaults to +- @cpp Shaders::Flat::bindTexture() @ce, + @cpp Shaders::Phong::bindAmbientTexture() @ce, + @cpp Shaders::Phong::bindDiffuseTexture() @ce, + @cpp Shaders::Phong::bindSpecularTexture() @ce and + @cpp Shaders::Phong::bindTextures() @ce now assert that the shader was + created with the corresponding flag enabled to prevent accidental "black + screen of death" errors. +- Ambient color in untextured @cpp Shaders::Phong @ce now defaults to @cpp 0x00000000_rgbaf @ce in order to support alpha-masked drawing out of the box @@ -2866,8 +2885,8 @@ Released 2018-10-23, tagged as - Vertex attribute divisor in @ref GL::Mesh::addVertexBufferInstanced() was not properly cleaned up after when @gl_extension{ARB,vertex_array_object} was disabled, causing subsequent draws to misbehave -- Fixed @ref Shaders::DistanceFieldVector and @ref Shaders::Vector to be - properly movable +- Fixed @cpp Shaders::DistanceFieldVector @ce and @cpp Shaders::Vector @ce to + be properly movable - Restored backwards compatibility to the templated @ref GL::Buffer::map() overload --- it was not possible to call it with @cpp void @ce template parameter @@ -2960,9 +2979,9 @@ Released 2018-10-23, tagged as tuple was deprecated, use the simpler version taking just @cpp Trade::MeshData2D @ce / @cpp Trade::MeshData3D @ce and directly returning a @ref GL::Mesh instead -- `Shaders::VertexColor::Color` is deprecated, use the direct - @ref Shaders::VertexColor::Color3 or @ref Shaders::VertexColor::Color4 - alternatives instead +- @cpp Shaders::VertexColor::Color @ce is deprecated, use the direct + @cpp Shaders::VertexColor::Color3 @ce or + @cpp Shaders::VertexColor::Color4 @ce alternatives instead - @cpp Trade::AbstractMaterialData @ce constructor taking just two parameters and @ref Trade::PhongMaterialData constructor taking three parameters are deprecated, use @cpp Trade::AbstractMaterialData::AbstractMaterialData(MaterialType, Flags, MaterialAlphaMode, Float, const void*) @ce @@ -3006,14 +3025,15 @@ Released 2018-10-23, tagged as are no longer @cpp virtual @ce functions. If you need to override their functionality, simply call the subclass implementation directly instead of calling it through a @ref SceneGraph::Camera. -- @ref Shaders::Flat::bindTexture(), @ref Shaders::Phong::bindAmbientTexture(), - @ref Shaders::Phong::bindDiffuseTexture(), - @ref Shaders::Phong::bindSpecularTexture() and - @ref Shaders::Phong::bindTextures() now assert that the shader was created - with the corresponding flag enabled to prevent accidental "black screen of - death" errors. This might cause your application to abort if it was calling - these functions when not needed. -- Ambient color in untextured @ref Shaders::Phong now defaults to +- @cpp Shaders::Flat::bindTexture() @ce, + @cpp Shaders::Phong::bindAmbientTexture() @ce, + @cpp Shaders::Phong::bindDiffuseTexture() @ce, + @cpp Shaders::Phong::bindSpecularTexture() @ce and + @cpp Shaders::Phong::bindTextures() @ce now assert that the shader was + created with the corresponding flag enabled to prevent accidental "black + screen of death" errors. This might cause your application to abort if it + was calling these functions when not needed. +- Ambient color in untextured @cpp Shaders::Phong @ce now defaults to @cpp 0x00000000_rgbaf @ce in order to support alpha-masked drawing out of the box. This may break code that assumed the alpha channel being opaque by default. diff --git a/doc/developers.dox b/doc/developers.dox index bebabdf9e..3c8ccd731 100644 --- a/doc/developers.dox +++ b/doc/developers.dox @@ -508,14 +508,14 @@ in inverse --- but usually @ref developers-deprecation "deprecate first". @section developers-adding-attribute Checklist for adding a new mesh attribute 1. Extend @ref Trade::MeshAttribute with the new entry -2. Add a corresponding reserved type to @ref Shaders::Generic, if not there +2. Add a corresponding reserved type to @ref Shaders::GenericGL, if not there already - Also update `src/Magnum/Shaders/generic.glsl` with the reserved ID 3. Update the type assertion in the @ref Trade::MeshAttributeData constructor to account for the new type 4. Add a pair of convenience getters to @ref Trade::MeshData similar to e.g. @ref Trade::MeshData::normalsInto() / @ref Trade::MeshData::normalsAsArray() - with a type that's the same as the one used in the @ref Shaders::Generic + with a type that's the same as the one used in the @ref Shaders::GenericGL definition, test that it does the right thing for every supported type 5. Update @ref Trade::operator<<(Debug&, MeshAttribute) for the new entry 6. Update @ref MeshTools::compile() to recognize the new attribute. If there diff --git a/doc/generated/primitives.cpp b/doc/generated/primitives.cpp index ab42a42de..ae3164a0e 100644 --- a/doc/generated/primitives.cpp +++ b/doc/generated/primitives.cpp @@ -71,10 +71,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -185,7 +185,7 @@ int PrimitiveVisualizer::exec() { GL::Renderer::setLineWidth(2.0f); { - Shaders::VertexColor2D shader; + Shaders::VertexColorGL2D shader; shader.setTransformationProjectionMatrix(Projection2D*Transformation2D); for(auto fun: {&PrimitiveVisualizer::axis2D}) { @@ -204,7 +204,7 @@ int PrimitiveVisualizer::exec() { } { - Shaders::VertexColor3D shader; + Shaders::VertexColorGL3D shader; shader.setTransformationProjectionMatrix(Projection3D*Transformation3D); for(auto fun: {&PrimitiveVisualizer::axis3D}) { @@ -223,7 +223,7 @@ int PrimitiveVisualizer::exec() { } { - Shaders::Flat2D shader; + Shaders::FlatGL2D shader; shader.setColor(OutlineColor) .setTransformationProjectionMatrix(Projection2D*Transformation2D); @@ -248,7 +248,7 @@ int PrimitiveVisualizer::exec() { } { - Shaders::Flat3D shader; + Shaders::FlatGL3D shader; shader.setColor(OutlineColor) .setTransformationProjectionMatrix(Projection3D*Transformation3D); @@ -278,7 +278,7 @@ int PrimitiveVisualizer::exec() { } } - Shaders::MeshVisualizer2D wireframe2D{Shaders::MeshVisualizer2D::Flag::Wireframe}; + Shaders::MeshVisualizerGL2D wireframe2D{Shaders::MeshVisualizerGL2D::Flag::Wireframe}; wireframe2D.setColor(0x00000000_srgbaf) .setWireframeColor(OutlineColor) .setWireframeWidth(2.0f) @@ -286,7 +286,7 @@ int PrimitiveVisualizer::exec() { .setTransformationProjectionMatrix(Projection2D*Transformation2D); { - Shaders::Flat2D flat; + Shaders::FlatGL2D flat; flat.setColor(BaseColor) .setTransformationProjectionMatrix(Projection2D*Transformation2D); @@ -309,7 +309,7 @@ int PrimitiveVisualizer::exec() { } } - Shaders::MeshVisualizer3D wireframe3D{Shaders::MeshVisualizer3D::Flag::Wireframe}; + Shaders::MeshVisualizerGL3D wireframe3D{Shaders::MeshVisualizerGL3D::Flag::Wireframe}; wireframe3D.setColor(0x00000000_srgbaf) .setWireframeColor(OutlineColor) .setWireframeWidth(2.0f) @@ -318,7 +318,7 @@ int PrimitiveVisualizer::exec() { .setProjectionMatrix(Projection3D); { - Shaders::Phong phong; + Shaders::PhongGL phong; phong.setAmbientColor(0x22272e_srgbf) .setDiffuseColor(BaseColor) .setSpecularColor(0x000000_srgbf) @@ -354,7 +354,7 @@ int PrimitiveVisualizer::exec() { } { - Shaders::VertexColor2D shader; + Shaders::VertexColorGL2D shader; shader.setTransformationProjectionMatrix(Projection2D*Transformation2D); for(auto fun: {&PrimitiveVisualizer::gradient2D, @@ -377,7 +377,7 @@ int PrimitiveVisualizer::exec() { } { - Shaders::VertexColor3D shader; + Shaders::VertexColorGL3D shader; shader.setTransformationProjectionMatrix(Projection3D*Transformation3D); for(auto fun: {&PrimitiveVisualizer::gradient3D, diff --git a/doc/generated/shaders.cpp b/doc/generated/shaders.cpp index 09dd64280..772959b7e 100644 --- a/doc/generated/shaders.cpp +++ b/doc/generated/shaders.cpp @@ -60,12 +60,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -162,7 +162,7 @@ namespace { } std::string ShaderVisualizer::phong() { - Shaders::Phong{} + Shaders::PhongGL{} .setAmbientColor(0x22272e_srgbf) .setDiffuseColor(BaseColor) .setShininess(200.0f) @@ -180,7 +180,7 @@ std::string ShaderVisualizer::meshVisualizer2D() { Matrix3::projection(Vector2{3.0f})* Matrix3::rotation(13.7_degf); - Shaders::MeshVisualizer2D{Shaders::MeshVisualizer2D::Flag::Wireframe} + Shaders::MeshVisualizerGL2D{Shaders::MeshVisualizerGL2D::Flag::Wireframe} .setColor(BaseColor) .setWireframeColor(OutlineColor) .setWireframeWidth(2.0f) @@ -206,7 +206,7 @@ std::string ShaderVisualizer::meshVisualizer2DPrimitiveId() { .setStorage(1, GL::TextureFormat::SRGB8Alpha8, size) .setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map}); - Shaders::MeshVisualizer2D{Shaders::MeshVisualizer2D::Flag::PrimitiveId} + Shaders::MeshVisualizerGL2D{Shaders::MeshVisualizerGL2D::Flag::PrimitiveId} .setTransformationProjectionMatrix(projection) .setColorMapTransformation(1.0f/255.0f, 1.0f/8.0f) .bindColorMapTexture(colorMapTexture) @@ -220,10 +220,10 @@ std::string ShaderVisualizer::meshVisualizer3D() { Matrix4::rotationZ(13.7_degf)* Matrix4::rotationX(-12.6_degf); - Shaders::MeshVisualizer3D{Shaders::MeshVisualizer3D::Flag::Wireframe| - Shaders::MeshVisualizer3D::Flag::TangentDirection| - Shaders::MeshVisualizer3D::Flag::BitangentFromTangentDirection| - Shaders::MeshVisualizer3D::Flag::NormalDirection} + Shaders::MeshVisualizerGL3D{Shaders::MeshVisualizerGL3D::Flag::Wireframe| + Shaders::MeshVisualizerGL3D::Flag::TangentDirection| + Shaders::MeshVisualizerGL3D::Flag::BitangentFromTangentDirection| + Shaders::MeshVisualizerGL3D::Flag::NormalDirection} .setColor(BaseColor) .setWireframeColor(OutlineColor) .setWireframeWidth(2.0f) @@ -253,7 +253,7 @@ std::string ShaderVisualizer::meshVisualizer3DPrimitiveId() { .setStorage(1, GL::TextureFormat::SRGB8Alpha8, size) .setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map}); - Shaders::MeshVisualizer3D{Shaders::MeshVisualizer3D::Flag::PrimitiveId} + Shaders::MeshVisualizerGL3D{Shaders::MeshVisualizerGL3D::Flag::PrimitiveId} .setTransformationMatrix(transformation) .setProjectionMatrix(Projection) .setColorMapTransformation(1.0f/255.0f, 1.0f/32.0f) @@ -264,7 +264,7 @@ std::string ShaderVisualizer::meshVisualizer3DPrimitiveId() { } std::string ShaderVisualizer::flat() { - Shaders::Flat3D{} + Shaders::FlatGL3D{} .setColor(BaseColor) .setTransformationProjectionMatrix(Projection*Transformation) .draw(MeshTools::compile(Primitives::uvSphereSolid(16, 32))); @@ -290,11 +290,11 @@ std::string ShaderVisualizer::vertexColor() { mesh.setPrimitive(GL::MeshPrimitive::Triangles) .setCount(sphere.indexCount()) .addVertexBuffer(vertices, 0, - Shaders::VertexColor3D::Position{}, - Shaders::VertexColor3D::Color3{}) + Shaders::VertexColorGL3D::Position{}, + Shaders::VertexColorGL3D::Color3{}) .setIndexBuffer(indices, 0, GL::MeshIndexType::UnsignedInt); - Shaders::VertexColor3D shader; + Shaders::VertexColorGL3D shader; shader.setTransformationProjectionMatrix(Projection*Transformation) .draw(mesh); @@ -319,7 +319,7 @@ std::string ShaderVisualizer::vector() { GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha); GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add); - Shaders::Vector2D{} + Shaders::VectorGL2D{} .setColor(BaseColor) .bindVectorTexture(texture) .setTransformationProjectionMatrix({}) @@ -348,7 +348,7 @@ std::string ShaderVisualizer::distanceFieldVector() { GL::Renderer::setBlendFunction(GL::Renderer::BlendFunction::One, GL::Renderer::BlendFunction::OneMinusSourceAlpha); GL::Renderer::setBlendEquation(GL::Renderer::BlendEquation::Add, GL::Renderer::BlendEquation::Add); - Shaders::DistanceFieldVector2D{} + Shaders::DistanceFieldVectorGL2D{} .setColor(BaseColor) .setOutlineColor(OutlineColor) .setOutlineRange(0.6f, 0.4f) diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 4af84179d..62c0ad507 100644 --- a/doc/namespaces.dox +++ b/doc/namespaces.dox @@ -446,19 +446,19 @@ See @ref building, @ref cmake and @ref shaders for more information. @m_div{m-col-m-4 m-col-t-6 m-text-center m-nopadt m-nopadx} @image html shaders-flat.png width=256px -@ref Flat @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** +@ref FlatGL @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** @m_enddiv @m_div{m-col-m-4 m-col-t-6 m-text-center m-nopadt m-nopadx} @image html shaders-phong.png width=256px -@ref Phong @m_class{m-label m-primary} **3D** +@ref PhongGL @m_class{m-label m-primary} **3D** @m_enddiv @m_div{m-clearfix-t} @m_enddiv @m_div{m-col-m-4 m-push-t-3 m-push-m-0 m-col-t-6 m-text-center m-nopadt m-nopadx} @image html shaders-vertexcolor.png width=256px -@ref VertexColor @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** +@ref VertexColorGL @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** @m_enddiv @endparblock @@ -471,22 +471,22 @@ See @ref building, @ref cmake and @ref shaders for more information. @m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx} @image html shaders-meshvisualizer2d.png width=256px -@ref MeshVisualizer2D "MeshVisualizer2D" @m_class{m-label m-success} **2D** +@ref MeshVisualizerGL2D @m_class{m-label m-success} **2D** @m_enddiv @m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx} @image html shaders-meshvisualizer3d.png width=256px -@ref MeshVisualizer3D "MeshVisualizer3D" @m_class{m-label m-primary} **3D** +@ref MeshVisualizerGL3D @m_class{m-label m-primary} **3D** @m_enddiv @m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx} @image html shaders-vector.png width=256px -@ref Vector @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** +@ref VectorGL @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** @m_enddiv @m_div{m-col-m-3 m-col-t-6 m-text-center m-nopadt m-nopadx} @image html shaders-distancefieldvector.png width=256px -@ref DistanceFieldVector @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** +@ref DistanceFieldVectorGL @m_class{m-label m-success} **2D** @m_class{m-label m-primary} **3D** @m_enddiv @endparblock diff --git a/doc/shaders.dox b/doc/shaders.dox index 40d7ff063..eb867025f 100644 --- a/doc/shaders.dox +++ b/doc/shaders.dox @@ -37,14 +37,16 @@ rendering and data visualization/debugging in both 2D and 3D scenes. The following shaders are available, see documentation of each class for sample output and example setup: -- @ref Shaders::Flat "Shaders::Flat*D" --- flat shading using single color or - texture -- @ref Shaders::Vector "Shaders::Vector*D" --- colored vector graphics -- @ref Shaders::DistanceFieldVector "Shaders::DistanceFieldVector*D" -- +- @ref Shaders::FlatGL "Shaders::FlatGL*D" --- flat shading using single + color or texture +- @ref Shaders::VectorGL "Shaders::VectorGL*D" --- colored vector graphics +- @ref Shaders::DistanceFieldVectorGL "Shaders::DistanceFieldVectorGL*D" -- colored and outlined vector graphics -- @ref Shaders::VertexColor "Shaders::VertexColor*D" --- vertex-colored meshes -- @ref Shaders::Phong --- Phong shading using colors or textures, 3D only -- @ref Shaders::MeshVisualizer --- wireframe visualization, 3D only +- @ref Shaders::VertexColorGL "Shaders::VertexColorGL*D" --- vertex-colored + meshes +- @ref Shaders::PhongGL --- Phong shading using colors or textures, 3D only +- @ref Shaders::MeshVisualizerGL2D / @ref Shaders::MeshVisualizerGL3D --- + wireframe visualization All the builtin shaders can be used on unextended OpenGL 2.1 and OpenGL ES 2.0 / WebGL 1.0, but they try to use the most recent technology available to have @@ -58,9 +60,9 @@ mesh and configuring the shader itself. Each shader expects some set of vertex attributes, thus when adding vertex buffer into the mesh, you need to specify which shader attributes are on which position in the buffer. See @ref GL::Mesh::addVertexBuffer() for details and -usage examples. Example mesh configuration for @ref Shaders::Phong shader: +usage examples. Example mesh configuration for @ref Shaders::PhongGL shader: -@snippet MagnumShaders.cpp shaders-setup +@snippet MagnumShaders-gl.cpp shaders-setup Each shader then has its own set of configuration functions. Some configuration is static, specified commonly as flags in constructor, directly affecting @@ -69,39 +71,39 @@ various binding points, commonly exposed through various setters. All shader uniforms have a reasonable defaults so you are able to see at least something when using the shader directly without any further configuration, but in most cases you may want to specify at least the transformation/projection matrices. -Example configuration and rendering using @link Shaders::Phong @endlink: +Example configuration and rendering using @link Shaders::PhongGL @endlink: -@snippet MagnumShaders.cpp shaders-rendering +@snippet MagnumShaders-gl.cpp shaders-rendering @section shaders-generic Generic vertex attributes and framebuffer attachments Many shaders share the same vertex attribute definitions, such as positions, normals, texture coordinates etc. It's thus possible to configure the mesh for a *generic* shader and then render it with any compatible shader. -Definition of all generic attributes is available in the @ref Shaders::Generic -class. Configuration of the above mesh using generic attributes could then look -like this: +Definition of all generic attributes is available in the +@ref Shaders::GenericGL class. Configuration of the above mesh using generic +attributes could then look like this: -@snippet MagnumShaders.cpp shaders-generic +@snippet MagnumShaders-gl.cpp shaders-generic Note that in this particular case both configurations are equivalent, because -@ref Shaders::Phong also uses generic vertex attribute definitions. Then you -can render the mesh using @ref Shaders::Phong shader like above, or use for -example @ref Shaders::Flat3D or even @ref Shaders::MeshVisualizer with the same -mesh reconfiguration. The unused attributes will be simply ignored. +@ref Shaders::PhongGL also uses generic vertex attribute definitions. Then you +can render the mesh using @ref Shaders::PhongGL shader like above, or use for +example @ref Shaders::FlatGL3D or even @ref Shaders::MeshVisualizerGL3D with +the same mesh reconfiguration. The unused attributes will be simply ignored. -@snippet MagnumShaders.cpp shaders-meshvisualizer +@snippet MagnumShaders-gl.cpp shaders-meshvisualizer The @ref MeshTools::compile() utility configures meshes using generic vertex attribute definitions to make them usable with any shader. -Besides vertex attributes, the @ref Shaders::Generic contains generic +Besides vertex attributes, the @ref Shaders::GenericGL contains generic definitions for framebuffer outputs as well --- in many cases a shader has just -one (color) output, but some shaders such as @ref Shaders::Flat or -@ref Shaders::Phong offer an object ID output as well. A setup equivalent to -what's done in Flat shader's @ref Shaders-Flat-object-id but using the generic -definitions would look like this: +one (color) output, but some shaders such as @ref Shaders::FlatGL or +@ref Shaders::PhongGL offer an object ID output as well. A setup equivalent to +what's done in Flat shader's @ref Shaders-FlatGL-object-id but using the +generic definitions would look like this: -@snippet MagnumShaders.cpp shaders-generic-object-id +@snippet MagnumShaders-gl.cpp shaders-generic-object-id */ } diff --git a/doc/snippets/CMakeLists.txt b/doc/snippets/CMakeLists.txt index 236b38714..dd8510fd4 100644 --- a/doc/snippets/CMakeLists.txt +++ b/doc/snippets/CMakeLists.txt @@ -86,7 +86,7 @@ if(WITH_GL) add_library(snippets-MagnumGL STATIC MagnumGL.cpp MagnumMeshTools-gl.cpp - MagnumShaders.cpp + MagnumShaders-gl.cpp MagnumText.cpp) target_link_libraries(snippets-MagnumGL PRIVATE MagnumGL) set_target_properties(snippets-MagnumGL PROPERTIES FOLDER "Magnum/doc/snippets") diff --git a/doc/snippets/MagnumGL.cpp b/doc/snippets/MagnumGL.cpp index 93e3880bd..a17f87d98 100644 --- a/doc/snippets/MagnumGL.cpp +++ b/doc/snippets/MagnumGL.cpp @@ -52,7 +52,7 @@ #include "Magnum/MeshTools/CompressIndices.h" #include "Magnum/Primitives/Cube.h" #include "Magnum/Primitives/Plane.h" -#include "Magnum/Shaders/Phong.h" +#include "Magnum/Shaders/PhongGL.h" #include "Magnum/Trade/MeshData.h" #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) @@ -1039,7 +1039,7 @@ buffer.setData(MeshTools::interleave(plane.positions3DAsArray(), GL::Mesh mesh; mesh.setPrimitive(plane.primitive()) .setCount(plane.vertexCount()) - .addVertexBuffer(buffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{}); + .addVertexBuffer(buffer, 0, Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{}); /* [Mesh-interleaved] */ } @@ -1099,7 +1099,7 @@ indexBuffer.setData(indexData); GL::Mesh mesh; mesh.setPrimitive(cube.primitive()) .setCount(cube.indexCount()) - .addVertexBuffer(vertexBuffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{}) + .addVertexBuffer(vertexBuffer, 0, Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{}) .setIndexBuffer(indexBuffer, 0, indexType); /* [Mesh-indexed-tools] */ } @@ -1169,14 +1169,14 @@ GL::Mesh mesh; GL::Buffer vertices, indices; // ... mesh.addVertexBuffer(std::move(vertices), 0, - Shaders::Phong::Position{}, - Shaders::Phong::Normal{}) + Shaders::PhongGL::Position{}, + Shaders::PhongGL::Normal{}) .setIndexBuffer(std::move(indices), 0, MeshIndexType::UnsignedInt); /* [Mesh-buffer-ownership] */ /* [Mesh-buffer-ownership-multiple] */ -mesh.addVertexBuffer(vertices, 0, Shaders::Phong::Position{}, 20) - .addVertexBuffer(std::move(vertices), 0, 20, Shaders::Phong::Normal{}); +mesh.addVertexBuffer(vertices, 0, Shaders::PhongGL::Position{}, 20) + .addVertexBuffer(std::move(vertices), 0, 20, Shaders::PhongGL::Normal{}); /* [Mesh-buffer-ownership-multiple] */ } @@ -1186,20 +1186,20 @@ GL::Buffer buffer; GL::Mesh mesh; mesh.addVertexBuffer(buffer, 76, /* initial array offset */ 4, /* skip vertex weight (Float) */ - Shaders::Phong::Position(), /* vertex position */ + Shaders::PhongGL::Position(), /* vertex position */ 8, /* skip texture coordinates (Vector2) */ - Shaders::Phong::Normal()); /* vertex normal */ + Shaders::PhongGL::Normal()); /* vertex normal */ /* [Mesh-addVertexBuffer1] */ /* [Mesh-addVertexBuffer2] */ -mesh.addVertexBuffer(buffer, 76, 4, Shaders::Phong::Position{}, 20) - .addVertexBuffer(buffer, 76, 24, Shaders::Phong::Normal{}, 0); +mesh.addVertexBuffer(buffer, 76, 4, Shaders::PhongGL::Position{}, 20) + .addVertexBuffer(buffer, 76, 24, Shaders::PhongGL::Normal{}, 0); /* [Mesh-addVertexBuffer2] */ /* [Mesh-addVertexBuffer3] */ Int vertexCount = 352; -mesh.addVertexBuffer(buffer, 76 + 4*vertexCount, Shaders::Phong::Position{}) - .addVertexBuffer(buffer, 76 + 24*vertexCount, Shaders::Phong::Normal{}); +mesh.addVertexBuffer(buffer, 76 + 4*vertexCount, Shaders::PhongGL::Position{}) + .addVertexBuffer(buffer, 76 + 24*vertexCount, Shaders::PhongGL::Normal{}); /* [Mesh-addVertexBuffer3] */ } diff --git a/doc/snippets/MagnumSceneGraph-gl.cpp b/doc/snippets/MagnumSceneGraph-gl.cpp index 8f22182a5..b5d99d6b3 100644 --- a/doc/snippets/MagnumSceneGraph-gl.cpp +++ b/doc/snippets/MagnumSceneGraph-gl.cpp @@ -39,8 +39,8 @@ #include "Magnum/SceneGraph/MatrixTransformation3D.h" #include "Magnum/SceneGraph/Object.h" #include "Magnum/SceneGraph/Scene.h" -#include "Magnum/Shaders/Flat.h" -#include "Magnum/Shaders/Phong.h" +#include "Magnum/Shaders/FlatGL.h" +#include "Magnum/Shaders/PhongGL.h" #include "Magnum/Trade/MeshData.h" using namespace Magnum; @@ -110,7 +110,7 @@ class RedCubeDrawable: public SceneGraph::Drawable3D { } GL::Mesh _mesh; - Shaders::Phong _shader; + Shaders::PhongGL _shader; }; /* [Drawable-usage] */ @@ -127,14 +127,14 @@ class RedCube: public Object3D, public SceneGraph::Drawable3D { void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) override; GL::Mesh _mesh; - Shaders::Phong _shader; + Shaders::PhongGL _shader; }; /* [Drawable-usage-multiple-inheritance] */ void draw(const Matrix4&, SceneGraph::Camera3D&); void draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) { /* [Drawable-usage-shader] */ -Shaders::Flat3D shader; +Shaders::FlatGL3D shader; shader.setTransformationProjectionMatrix( camera.projectionMatrix()*transformationMatrix); /* [Drawable-usage-shader] */ @@ -188,7 +188,7 @@ struct MyApplication: Platform::Application { /* [Drawable-multiple-groups] */ // ... - Shaders::Phong _shader; + Shaders::PhongGL _shader; SceneGraph::DrawableGroup3D _phongObjects, _transparentObjects; }; diff --git a/doc/snippets/MagnumShaders.cpp b/doc/snippets/MagnumShaders-gl.cpp similarity index 70% rename from doc/snippets/MagnumShaders.cpp rename to doc/snippets/MagnumShaders-gl.cpp index f607c50b0..96177ac94 100644 --- a/doc/snippets/MagnumShaders.cpp +++ b/doc/snippets/MagnumShaders-gl.cpp @@ -46,12 +46,12 @@ #include "Magnum/Math/Matrix4.h" #include "Magnum/Math/FunctionsBatch.h" #include "Magnum/MeshTools/Duplicate.h" -#include "Magnum/Shaders/DistanceFieldVector.h" -#include "Magnum/Shaders/Flat.h" -#include "Magnum/Shaders/MeshVisualizer.h" -#include "Magnum/Shaders/Phong.h" -#include "Magnum/Shaders/Vector.h" -#include "Magnum/Shaders/VertexColor.h" +#include "Magnum/Shaders/DistanceFieldVectorGL.h" +#include "Magnum/Shaders/FlatGL.h" +#include "Magnum/Shaders/MeshVisualizerGL.h" +#include "Magnum/Shaders/PhongGL.h" +#include "Magnum/Shaders/VectorGL.h" +#include "Magnum/Shaders/VertexColorGL.h" #include "Magnum/Trade/LightData.h" #define DOXYGEN_IGNORE(...) __VA_ARGS__ @@ -80,9 +80,9 @@ vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.addVertexBuffer(vertices, 0, - Shaders::Phong::Position{}, - Shaders::Phong::Normal{}, - Shaders::Phong::TextureCoordinates{}) + Shaders::PhongGL::Position{}, + Shaders::PhongGL::Normal{}, + Shaders::PhongGL::TextureCoordinates{}) //... ; /* [shaders-setup] */ @@ -91,7 +91,7 @@ mesh.addVertexBuffer(vertices, 0, Matrix4 transformationMatrix, projectionMatrix; GL::Texture2D diffuseTexture, specularTexture; -Shaders::Phong shader{Shaders::Phong::Flag::DiffuseTexture}; +Shaders::PhongGL shader{Shaders::PhongGL::Flag::DiffuseTexture}; shader.bindDiffuseTexture(diffuseTexture) .setTransformationMatrix(transformationMatrix) .setNormalMatrix(transformationMatrix.normalMatrix()) @@ -101,13 +101,13 @@ shader.bindDiffuseTexture(diffuseTexture) /* [shaders-generic] */ mesh.addVertexBuffer(vertices, 0, - Shaders::Generic3D::Position{}, - Shaders::Generic3D::Normal{}, - Shaders::Generic3D::TextureCoordinates{}); + Shaders::GenericGL3D::Position{}, + Shaders::GenericGL3D::Normal{}, + Shaders::GenericGL3D::TextureCoordinates{}); /* [shaders-generic] */ /* [shaders-meshvisualizer] */ -Shaders::MeshVisualizer3D visualizerShader{Shaders::MeshVisualizer3D::Flag::Wireframe}; +Shaders::MeshVisualizerGL3D visualizerShader{Shaders::MeshVisualizerGL3D::Flag::Wireframe}; visualizerShader .setColor(0x2f83cc_rgbf) .setWireframeColor(0xdcdcdc_rgbf) @@ -119,7 +119,7 @@ visualizerShader } { -/* [DistanceFieldVector-usage1] */ +/* [DistanceFieldVectorGL-usage1] */ struct Vertex { Vector2 position; Vector2 textureCoordinates; @@ -133,31 +133,31 @@ vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.addVertexBuffer(vertices, 0, - Shaders::DistanceFieldVector2D::Position{}, - Shaders::DistanceFieldVector2D::TextureCoordinates{}) + Shaders::DistanceFieldVectorGL2D::Position{}, + Shaders::DistanceFieldVectorGL2D::TextureCoordinates{}) // ... ; -/* [DistanceFieldVector-usage1] */ +/* [DistanceFieldVectorGL-usage1] */ } { GL::Mesh mesh; -/* [DistanceFieldVector-usage2] */ +/* [DistanceFieldVectorGL-usage2] */ Matrix3 transformationMatrix, projectionMatrix; GL::Texture2D texture; -Shaders::DistanceFieldVector2D shader; +Shaders::DistanceFieldVectorGL2D shader; shader.setColor(0x2f83cc_rgbf) .setOutlineColor(0xdcdcdc_rgbf) .setOutlineRange(0.6f, 0.4f) .bindVectorTexture(texture) .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) .draw(mesh); -/* [DistanceFieldVector-usage2] */ +/* [DistanceFieldVectorGL-usage2] */ } { -/* [Flat-usage-colored1] */ +/* [FlatGL-usage-colored1] */ struct Vertex { Vector3 position; }; @@ -169,25 +169,25 @@ GL::Buffer vertices; vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; -mesh.addVertexBuffer(vertices, 0, Shaders::Flat3D::Position{}) +mesh.addVertexBuffer(vertices, 0, Shaders::FlatGL3D::Position{}) // ... ; -/* [Flat-usage-colored1] */ +/* [FlatGL-usage-colored1] */ -/* [Flat-usage-colored2] */ +/* [FlatGL-usage-colored2] */ Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); Matrix4 projectionMatrix = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); -Shaders::Flat3D shader; +Shaders::FlatGL3D shader; shader.setColor(0x2f83cc_rgbf) .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) .draw(mesh); -/* [Flat-usage-colored2] */ +/* [FlatGL-usage-colored2] */ } { -/* [Flat-usage-textured1] */ +/* [FlatGL-usage-textured1] */ struct Vertex { Vector3 position; Vector2 textureCoordinates; @@ -201,21 +201,21 @@ vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.addVertexBuffer(vertices, 0, - Shaders::Flat3D::Position{}, - Shaders::Flat3D::TextureCoordinates{}) + Shaders::FlatGL3D::Position{}, + Shaders::FlatGL3D::TextureCoordinates{}) // ... ; -/* [Flat-usage-textured1] */ +/* [FlatGL-usage-textured1] */ -/* [Flat-usage-textured2] */ +/* [FlatGL-usage-textured2] */ Matrix4 transformationMatrix, projectionMatrix; GL::Texture2D texture; -Shaders::Flat3D shader{Shaders::Flat3D::Flag::Textured}; +Shaders::FlatGL3D shader{Shaders::FlatGL3D::Flag::Textured}; shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) .bindTexture(texture) .draw(mesh); -/* [Flat-usage-textured2] */ +/* [FlatGL-usage-textured2] */ } #ifndef MAGNUM_TARGET_GLES2 @@ -224,39 +224,39 @@ GL::Framebuffer framebuffer{{}}; GL::Mesh mesh; Vector2i size; UnsignedInt meshId{}; -/* [Flat-usage-object-id] */ +/* [FlatGL-usage-object-id] */ GL::Renderbuffer color, objectId; color.setStorage(GL::RenderbufferFormat::RGBA8, size); objectId.setStorage(GL::RenderbufferFormat::R16UI, size); // large as needed framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, color) .attachRenderbuffer(GL::Framebuffer::ColorAttachment{1}, objectId); -Shaders::Flat3D shader{Shaders::Flat3D::Flag::ObjectId}; +Shaders::FlatGL3D shader{Shaders::FlatGL3D::Flag::ObjectId}; // ... framebuffer.mapForDraw({ - {Shaders::Flat3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, - {Shaders::Flat3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}}) + {Shaders::FlatGL3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, + {Shaders::FlatGL3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}}) .clearColor(0, 0x1f1f1f_rgbf) .clearColor(1, Vector4ui{0}) .bind(); shader.setObjectId(meshId) .draw(mesh); -/* [Flat-usage-object-id] */ +/* [FlatGL-usage-object-id] */ /* [shaders-generic-object-id] */ framebuffer.mapForDraw({ - {Shaders::Generic3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, - {Shaders::Generic3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}}); + {Shaders::GenericGL3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, + {Shaders::GenericGL3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}}}); /* [shaders-generic-object-id] */ } #endif { GL::Mesh mesh; -/* [Flat-usage-instancing] */ +/* [FlatGL-usage-instancing] */ struct { Matrix4 transformation; Color3 color; @@ -269,38 +269,38 @@ struct { mesh.setInstanceCount(Containers::arraySize(instanceData)) .addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0, - Shaders::Flat3D::TransformationMatrix{}, - Shaders::Flat3D::Color3{}); -/* [Flat-usage-instancing] */ + Shaders::FlatGL3D::TransformationMatrix{}, + Shaders::FlatGL3D::Color3{}); +/* [FlatGL-usage-instancing] */ } { struct: GL::AbstractShaderProgram { void foo() { -/* [Generic-custom-bind] */ -bindAttributeLocation(Shaders::Generic3D::Position::Location, "position"); -bindAttributeLocation(Shaders::Generic3D::Normal::Location, "normal"); -/* [Generic-custom-bind] */ +/* [GenericGL-custom-bind] */ +bindAttributeLocation(Shaders::GenericGL3D::Position::Location, "position"); +bindAttributeLocation(Shaders::GenericGL3D::Normal::Location, "normal"); +/* [GenericGL-custom-bind] */ } } shader; } { GL::Shader vert{GL::Version::None, GL::Shader::Type::Vertex}; -/* [Generic-custom-preprocessor] */ +/* [GenericGL-custom-preprocessor] */ vert.addSource(Utility::formatString( "#define POSITION_ATTRIBUTE_LOCATION {}\n" "#define NORMAL_ATTRIBUTE_LOCATION {}\n", - Shaders::Generic3D::Position::Location, - Shaders::Generic3D::Normal::Location)) + Shaders::GenericGL3D::Position::Location, + Shaders::GenericGL3D::Normal::Location)) // … .addFile("MyShader.vert"); -/* [Generic-custom-preprocessor] */ +/* [GenericGL-custom-preprocessor] */ } { GL::Mesh mesh; -/* [Phong-usage-instancing] */ +/* [PhongGL-usage-instancing] */ struct { Matrix4 transformation; Matrix3x3 normal; @@ -315,13 +315,13 @@ for(auto& instance: instanceData) mesh.setInstanceCount(Containers::arraySize(instanceData)) .addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0, - Shaders::Phong::TransformationMatrix{}, - Shaders::Phong::NormalMatrix{}); -/* [Phong-usage-instancing] */ + Shaders::PhongGL::TransformationMatrix{}, + Shaders::PhongGL::NormalMatrix{}); +/* [PhongGL-usage-instancing] */ } { -/* [MeshVisualizer-usage-geom1] */ +/* [MeshVisualizerGL3D-usage-geom1] */ struct Vertex { Vector3 position; }; @@ -333,32 +333,32 @@ GL::Buffer vertices; vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; -mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizer3D::Position{}); -/* [MeshVisualizer-usage-geom1] */ +mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizerGL3D::Position{}); +/* [MeshVisualizerGL3D-usage-geom1] */ -/* [MeshVisualizer-usage-geom2] */ +/* [MeshVisualizerGL3D-usage-geom2] */ Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); Matrix4 projectionMatrix = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); -Shaders::MeshVisualizer3D shader{Shaders::MeshVisualizer3D::Flag::Wireframe}; +Shaders::MeshVisualizerGL3D shader{Shaders::MeshVisualizerGL3D::Flag::Wireframe}; shader.setColor(0x2f83cc_rgbf) .setWireframeColor(0xdcdcdc_rgbf) .setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()}) .setTransformationMatrix(transformationMatrix) .setProjectionMatrix(projectionMatrix) .draw(mesh); -/* [MeshVisualizer-usage-geom2] */ +/* [MeshVisualizerGL3D-usage-geom2] */ -/* [MeshVisualizer-usage-no-geom-old] */ +/* [MeshVisualizerGL3D-usage-no-geom-old] */ Containers::Array vertexIndex{Containers::arraySize(data)}; std::iota(vertexIndex.begin(), vertexIndex.end(), 0.0f); GL::Buffer vertexIndices; vertexIndices.setData(vertexIndex, GL::BufferUsage::StaticDraw); -mesh.addVertexBuffer(vertexIndices, 0, Shaders::MeshVisualizer3D::VertexIndex{}); -/* [MeshVisualizer-usage-no-geom-old] */ +mesh.addVertexBuffer(vertexIndices, 0, Shaders::MeshVisualizerGL3D::VertexIndex{}); +/* [MeshVisualizerGL3D-usage-no-geom-old] */ } #endif @@ -367,7 +367,7 @@ mesh.addVertexBuffer(vertexIndices, 0, Shaders::MeshVisualizer3D::VertexIndex{}) on GCC 4.8 in the [60] array */ #if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500 { -/* [MeshVisualizer-usage-tbn1] */ +/* [MeshVisualizerGL3D-usage-tbn1] */ struct Vertex { Vector3 position; Vector4 tangent; @@ -382,32 +382,32 @@ vertices.setData(data); GL::Mesh mesh; mesh.addVertexBuffer(vertices, 0, - Shaders::MeshVisualizer3D::Position{}, - Shaders::MeshVisualizer3D::Tangent4{}, - Shaders::MeshVisualizer3D::Normal{}); -/* [MeshVisualizer-usage-tbn1] */ + Shaders::MeshVisualizerGL3D::Position{}, + Shaders::MeshVisualizerGL3D::Tangent4{}, + Shaders::MeshVisualizerGL3D::Normal{}); +/* [MeshVisualizerGL3D-usage-tbn1] */ -/* [MeshVisualizer-usage-tbn2] */ +/* [MeshVisualizerGL3D-usage-tbn2] */ Matrix4 transformationMatrix, projectionMatrix; -Shaders::MeshVisualizer3D shader{ - Shaders::MeshVisualizer3D::Flag::TangentDirection| - Shaders::MeshVisualizer3D::Flag::BitangentFromTangentDirection| - Shaders::MeshVisualizer3D::Flag::NormalDirection}; +Shaders::MeshVisualizerGL3D shader{ + Shaders::MeshVisualizerGL3D::Flag::TangentDirection| + Shaders::MeshVisualizerGL3D::Flag::BitangentFromTangentDirection| + Shaders::MeshVisualizerGL3D::Flag::NormalDirection}; shader.setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()}) .setTransformationMatrix(transformationMatrix) .setProjectionMatrix(projectionMatrix) .setNormalMatrix(transformationMatrix.normalMatrix()) .setLineLength(0.3f) .draw(mesh); -/* [MeshVisualizer-usage-tbn2] */ +/* [MeshVisualizerGL3D-usage-tbn2] */ } #endif #endif { -/* [MeshVisualizer-usage-no-geom1] */ +/* [MeshVisualizerGL3D-usage-no-geom1] */ Containers::StridedArrayView1D indices; Containers::StridedArrayView1D indexedPositions; @@ -415,24 +415,24 @@ Containers::StridedArrayView1D indexedPositions; GL::Buffer vertices{MeshTools::duplicate(indices, indexedPositions)}; GL::Mesh mesh; -mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizer3D::Position{}); -/* [MeshVisualizer-usage-no-geom1] */ +mesh.addVertexBuffer(vertices, 0, Shaders::MeshVisualizerGL3D::Position{}); +/* [MeshVisualizerGL3D-usage-no-geom1] */ } { GL::Mesh mesh; -/* [MeshVisualizer-usage-no-geom2] */ +/* [MeshVisualizerGL3D-usage-no-geom2] */ Matrix4 transformationMatrix, projectionMatrix; -Shaders::MeshVisualizer3D shader{ - Shaders::MeshVisualizer3D::Flag::Wireframe| - Shaders::MeshVisualizer3D::Flag::NoGeometryShader}; +Shaders::MeshVisualizerGL3D shader{ + Shaders::MeshVisualizerGL3D::Flag::Wireframe| + Shaders::MeshVisualizerGL3D::Flag::NoGeometryShader}; shader.setColor(0x2f83cc_rgbf) .setWireframeColor(0xdcdcdc_rgbf) .setTransformationMatrix(transformationMatrix) .setProjectionMatrix(projectionMatrix) .draw(mesh); -/* [MeshVisualizer-usage-no-geom2] */ +/* [MeshVisualizerGL3D-usage-no-geom2] */ } #ifndef MAGNUM_TARGET_GLES2 @@ -440,7 +440,7 @@ shader.setColor(0x2f83cc_rgbf) GL::Mesh mesh; Containers::ArrayView objectIds; Matrix4 transformationMatrix, projectionMatrix; -/* [MeshVisualizer-usage-object-id] */ +/* [MeshVisualizerGL3D-usage-object-id] */ const auto map = DebugTools::ColorMap::turbo(); const Vector2i size{Int(map.size()), 1}; @@ -452,20 +452,20 @@ colorMapTexture .setStorage(1, GL::TextureFormat::RGBA8, size) .setSubImage(0, {}, ImageView2D{PixelFormat::RGB8Srgb, size, map}); -Shaders::MeshVisualizer3D shader{ - Shaders::MeshVisualizer3D::Flag::InstancedObjectId}; +Shaders::MeshVisualizerGL3D shader{ + Shaders::MeshVisualizerGL3D::Flag::InstancedObjectId}; shader.setColorMapTransformation(0.0f, 1.0f/Math::max(objectIds)) .setTransformationMatrix(transformationMatrix) .setProjectionMatrix(projectionMatrix) .bindColorMapTexture(colorMapTexture) .draw(mesh); -/* [MeshVisualizer-usage-object-id] */ +/* [MeshVisualizerGL3D-usage-object-id] */ } #endif #if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500 { -/* [Phong-usage-colored1] */ +/* [PhongGL-usage-colored1] */ struct Vertex { Vector3 position; Vector3 normal; @@ -479,27 +479,27 @@ vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.addVertexBuffer(vertices, 0, - Shaders::Phong::Position{}, - Shaders::Phong::Normal{}); -/* [Phong-usage-colored1] */ + Shaders::PhongGL::Position{}, + Shaders::PhongGL::Normal{}); +/* [PhongGL-usage-colored1] */ -/* [Phong-usage-colored2] */ +/* [PhongGL-usage-colored2] */ Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); Matrix4 projectionMatrix = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); -Shaders::Phong shader; +Shaders::PhongGL shader; shader.setDiffuseColor(0x2f83cc_rgbf) .setShininess(200.0f) .setTransformationMatrix(transformationMatrix) .setNormalMatrix(transformationMatrix.normalMatrix()) .setProjectionMatrix(projectionMatrix) .draw(mesh); -/* [Phong-usage-colored2] */ +/* [PhongGL-usage-colored2] */ } { -/* [Phong-usage-texture1] */ +/* [PhongGL-usage-texture1] */ struct Vertex { Vector3 position; Vector3 normal; @@ -514,31 +514,31 @@ vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.addVertexBuffer(vertices, 0, - Shaders::Phong::Position{}, - Shaders::Phong::Normal{}, - Shaders::Phong::TextureCoordinates{}); -/* [Phong-usage-texture1] */ + Shaders::PhongGL::Position{}, + Shaders::PhongGL::Normal{}, + Shaders::PhongGL::TextureCoordinates{}); +/* [PhongGL-usage-texture1] */ -/* [Phong-usage-texture2] */ +/* [PhongGL-usage-texture2] */ Matrix4 transformationMatrix, projectionMatrix; GL::Texture2D diffuseTexture, specularTexture; -Shaders::Phong shader{Shaders::Phong::Flag::DiffuseTexture| - Shaders::Phong::Flag::SpecularTexture}; +Shaders::PhongGL shader{Shaders::PhongGL::Flag::DiffuseTexture| + Shaders::PhongGL::Flag::SpecularTexture}; shader.bindTextures(nullptr, &diffuseTexture, &specularTexture, nullptr) .setTransformationMatrix(transformationMatrix) .setNormalMatrix(transformationMatrix.normalMatrix()) .setProjectionMatrix(projectionMatrix) .draw(mesh); -/* [Phong-usage-texture2] */ +/* [PhongGL-usage-texture2] */ } #endif { -/* [Phong-usage-lights] */ +/* [PhongGL-usage-lights] */ Matrix4 directionalLight, pointLight1, pointLight2; // camera-relative -Shaders::Phong shader{{}, 3}; // 3 lights +Shaders::PhongGL shader{{}, 3}; // 3 lights shader .setLightPositions({Vector4{directionalLight.up(), 0.0f}, Vector4{pointLight1.translation(), 1.0f}, @@ -550,39 +550,39 @@ shader .setLightRanges({Constants::inf(), 2.0f, 2.0f}); -/* [Phong-usage-lights] */ +/* [PhongGL-usage-lights] */ } { Color3 ambientColor; GL::Texture2D diffuseTexture; -/* [Phong-usage-lights-ambient] */ +/* [PhongGL-usage-lights-ambient] */ Trade::LightData ambientLight = DOXYGEN_IGNORE(Trade::LightData{{}, {}, {}}); -Shaders::Phong shader{Shaders::Phong::Flag::AmbientTexture|DOXYGEN_IGNORE(Shaders::Phong::Flag::DiffuseTexture), DOXYGEN_IGNORE(3)}; +Shaders::PhongGL shader{Shaders::PhongGL::Flag::AmbientTexture|DOXYGEN_IGNORE(Shaders::PhongGL::Flag::DiffuseTexture), DOXYGEN_IGNORE(3)}; shader .setAmbientColor(ambientColor + ambientLight.color()*ambientLight.intensity()) .bindAmbientTexture(diffuseTexture) .bindDiffuseTexture(diffuseTexture); -/* [Phong-usage-lights-ambient] */ +/* [PhongGL-usage-lights-ambient] */ } { GL::Texture2D diffuseAlphaTexture; Color3 diffuseRgb, specularRgb; -/* [Phong-usage-alpha] */ -Shaders::Phong shader{Shaders::Phong::Flag::AmbientTexture| - Shaders::Phong::Flag::DiffuseTexture}; +/* [PhongGL-usage-alpha] */ +Shaders::PhongGL shader{Shaders::PhongGL::Flag::AmbientTexture| + Shaders::PhongGL::Flag::DiffuseTexture}; shader.bindTextures(&diffuseAlphaTexture, &diffuseAlphaTexture, nullptr, nullptr) .setAmbientColor(0x000000ff_rgbaf) .setDiffuseColor(Color4{diffuseRgb, 0.0f}) .setSpecularColor(Color4{specularRgb, 0.0f}); -/* [Phong-usage-alpha] */ +/* [PhongGL-usage-alpha] */ } #if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500 { -/* [Vector-usage1] */ +/* [VectorGL-usage1] */ struct Vertex { Vector2 position; Vector2 textureCoordinates; @@ -596,24 +596,24 @@ vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.addVertexBuffer(vertices, 0, - Shaders::Vector2D::Position{}, - Shaders::Vector2D::TextureCoordinates{}); -/* [Vector-usage1] */ + Shaders::VectorGL2D::Position{}, + Shaders::VectorGL2D::TextureCoordinates{}); +/* [VectorGL-usage1] */ -/* [Vector-usage2] */ +/* [VectorGL-usage2] */ Matrix3 transformationMatrix, projectionMatrix; GL::Texture2D texture; -Shaders::Vector2D shader; +Shaders::VectorGL2D shader; shader.setColor(0x2f83cc_rgbf) .bindVectorTexture(texture) .setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) .draw(mesh); -/* [Vector-usage2] */ +/* [VectorGL-usage2] */ } { -/* [VertexColor-usage1] */ +/* [VertexColorGL-usage1] */ struct Vertex { Vector3 position; Color3 color; @@ -627,19 +627,19 @@ vertices.setData(data, GL::BufferUsage::StaticDraw); GL::Mesh mesh; mesh.addVertexBuffer(vertices, 0, - Shaders::VertexColor3D::Position{}, - Shaders::VertexColor3D::Color3{}); -/* [VertexColor-usage1] */ + Shaders::VertexColorGL3D::Position{}, + Shaders::VertexColorGL3D::Color3{}); +/* [VertexColorGL-usage1] */ -/* [VertexColor-usage2] */ +/* [VertexColorGL-usage2] */ Matrix4 transformationMatrix = Matrix4::translation(Vector3::zAxis(-5.0f)); Matrix4 projectionMatrix = Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.001f, 100.0f); -Shaders::VertexColor3D shader; +Shaders::VertexColorGL3D shader; shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix) .draw(mesh); -/* [VertexColor-usage2] */ +/* [VertexColorGL-usage2] */ } #endif diff --git a/doc/snippets/MagnumText.cpp b/doc/snippets/MagnumText.cpp index d614a2a61..5f4d4675d 100644 --- a/doc/snippets/MagnumText.cpp +++ b/doc/snippets/MagnumText.cpp @@ -32,7 +32,7 @@ #include "Magnum/FileCallback.h" #include "Magnum/Math/Color.h" #include "Magnum/Math/Matrix3.h" -#include "Magnum/Shaders/Vector.h" +#include "Magnum/Shaders/VectorGL.h" #include "Magnum/Text/AbstractFont.h" #include "Magnum/Text/DistanceFieldGlyphCache.h" #include "Magnum/Text/Renderer.h" @@ -144,7 +144,7 @@ font->fillGlyphCache(cache, "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789?!:;,. "); -Shaders::Vector2D shader; +Shaders::VectorGL2D shader; GL::Buffer vertexBuffer, indexBuffer; GL::Mesh mesh; diff --git a/doc/snippets/MagnumTrade.cpp b/doc/snippets/MagnumTrade.cpp index a944f7eaf..e101b52f5 100644 --- a/doc/snippets/MagnumTrade.cpp +++ b/doc/snippets/MagnumTrade.cpp @@ -54,7 +54,7 @@ #include "Magnum/GL/TextureFormat.h" #include "Magnum/GL/Mesh.h" #include "Magnum/MeshTools/Compile.h" -#include "Magnum/Shaders/Phong.h" +#include "Magnum/Shaders/PhongGL.h" #endif #ifdef MAGNUM_TARGET_VK #include "Magnum/Vk/Vulkan.h" @@ -544,7 +544,7 @@ GL::Buffer vertices; vertices.setData(MeshTools::interleave(data.positions3DAsArray(), data.normalsAsArray())); mesh.addVertexBuffer(std::move(vertices), 0, - Shaders::Phong::Position{}, Shaders::Phong::Normal{}); + Shaders::PhongGL::Position{}, Shaders::PhongGL::Normal{}); /* Set up an index buffer, if the mesh is indexed*/ if(data.isIndexed()) { @@ -568,12 +568,12 @@ vertices.setData(data.vertexData()); mesh.addVertexBuffer(vertices, data.attributeOffset(Trade::MeshAttribute::Position), data.attributeStride(Trade::MeshAttribute::Position), - GL::DynamicAttribute{Shaders::Phong::Position{}, + GL::DynamicAttribute{Shaders::PhongGL::Position{}, data.attributeFormat(Trade::MeshAttribute::Position)}); mesh.addVertexBuffer(vertices, data.attributeOffset(Trade::MeshAttribute::Normal), data.attributeStride(Trade::MeshAttribute::Normal), - GL::DynamicAttribute{Shaders::Phong::Normal{}, + GL::DynamicAttribute{Shaders::PhongGL::Normal{}, data.attributeFormat(Trade::MeshAttribute::Normal)}); // Set up other attributes ... diff --git a/src/Magnum/DebugTools/ForceRenderer.cpp b/src/Magnum/DebugTools/ForceRenderer.cpp index 49b0b39bb..2cfabcf08 100644 --- a/src/Magnum/DebugTools/ForceRenderer.cpp +++ b/src/Magnum/DebugTools/ForceRenderer.cpp @@ -28,7 +28,7 @@ #include "Magnum/GL/Mesh.h" #include "Magnum/DebugTools/ResourceManager.h" #include "Magnum/SceneGraph/Camera.h" -#include "Magnum/Shaders/Flat.h" +#include "Magnum/Shaders/FlatGL.h" #include "Magnum/DebugTools/Implementation/ForceRendererTransformation.h" @@ -57,8 +57,8 @@ constexpr UnsignedByte indices[]{ template ForceRenderer::ForceRenderer(ResourceManager& manager, SceneGraph::AbstractObject& object, const VectorTypeFor& forcePosition, const VectorTypeFor& force, ResourceKey options, SceneGraph::DrawableGroup* drawables): SceneGraph::Drawable(object, drawables), _forcePosition(forcePosition), _force(force), _options(manager.get(options)) { /* Shader */ - _shader = manager.get>(shaderKey()); - if(!_shader) manager.set(_shader.key(), new Shaders::Flat); + _shader = manager.get>(shaderKey()); + if(!_shader) manager.set(_shader.key(), new Shaders::FlatGL); /* Mesh and vertex buffer */ _mesh = manager.get("force"); @@ -72,7 +72,7 @@ template ForceRenderer::ForceRenderer(Resour GL::Mesh mesh{GL::MeshPrimitive::Lines}; mesh.setCount(Containers::arraySize(indices)) .addVertexBuffer(std::move(vertexBuffer), 0, - typename Shaders::Flat::Position(Shaders::Flat::Position::Components::Two)) + typename Shaders::FlatGL::Position(Shaders::FlatGL::Position::Components::Two)) .setIndexBuffer(std::move(indexBuffer), 0, GL::MeshIndexType::UnsignedByte, 0, Containers::arraySize(positions)); manager.set(_mesh.key(), std::move(mesh), ResourceDataState::Final, ResourcePolicy::Manual); } diff --git a/src/Magnum/DebugTools/ForceRenderer.h b/src/Magnum/DebugTools/ForceRenderer.h index c78482e36..2b59950a9 100644 --- a/src/Magnum/DebugTools/ForceRenderer.h +++ b/src/Magnum/DebugTools/ForceRenderer.h @@ -162,7 +162,7 @@ template class ForceRenderer: public SceneGraph::Drawabl const VectorTypeFor& _force; Resource _options; - Resource> _shader; + Resource> _shader; Resource _mesh; }; diff --git a/src/Magnum/DebugTools/ObjectRenderer.cpp b/src/Magnum/DebugTools/ObjectRenderer.cpp index 12a829626..73e4bbc4c 100644 --- a/src/Magnum/DebugTools/ObjectRenderer.cpp +++ b/src/Magnum/DebugTools/ObjectRenderer.cpp @@ -30,7 +30,7 @@ #include "Magnum/MeshTools/Compile.h" #include "Magnum/Primitives/Axis.h" #include "Magnum/SceneGraph/Camera.h" -#include "Magnum/Shaders/VertexColor.h" +#include "Magnum/Shaders/VertexColorGL.h" #include "Magnum/Trade/MeshData.h" namespace Magnum { namespace DebugTools { @@ -56,8 +56,8 @@ template<> struct Renderer<3> { /* Doxygen gets confused when using {} to initialize parent object */ template ObjectRenderer::ObjectRenderer(ResourceManager& manager, SceneGraph::AbstractObject& object, ResourceKey options, SceneGraph::DrawableGroup* drawables): SceneGraph::Drawable(object, drawables), _options{manager.get(options)} { /* Shader */ - _shader = manager.get>(Renderer::shader()); - if(!_shader) manager.set(_shader.key(), new Shaders::VertexColor); + _shader = manager.get>(Renderer::shader()); + if(!_shader) manager.set(_shader.key(), new Shaders::VertexColorGL); /* Mesh */ _mesh = manager.get(Renderer::mesh()); diff --git a/src/Magnum/DebugTools/ObjectRenderer.h b/src/Magnum/DebugTools/ObjectRenderer.h index af1d7bfdf..bd6d3310c 100644 --- a/src/Magnum/DebugTools/ObjectRenderer.h +++ b/src/Magnum/DebugTools/ObjectRenderer.h @@ -121,7 +121,7 @@ template class ObjectRenderer: public SceneGraph::Drawab void draw(const MatrixTypeFor& transformationMatrix, SceneGraph::Camera& camera) override; Resource _options; - Resource> _shader; + Resource> _shader; Resource _mesh; }; diff --git a/src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp b/src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp index 6347e5ba2..0b85d9646 100644 --- a/src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp +++ b/src/Magnum/DebugTools/Test/FrameProfilerGLTest.cpp @@ -36,7 +36,7 @@ #include "Magnum/GL/RenderbufferFormat.h" #include "Magnum/MeshTools/Compile.h" #include "Magnum/Primitives/Cube.h" -#include "Magnum/Shaders/Flat.h" +#include "Magnum/Shaders/FlatGL.h" #include "Magnum/Trade/MeshData.h" namespace Magnum { namespace DebugTools { namespace Test { namespace { @@ -109,7 +109,7 @@ void FrameProfilerGLTest::test() { fb.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, color) .bind(); - Shaders::Flat3D shader; + Shaders::FlatGL3D shader; GL::Mesh mesh = MeshTools::compile(Primitives::cubeSolid()); FrameProfilerGL profiler{data.values, 4}; diff --git a/src/Magnum/GL/Framebuffer.h b/src/Magnum/GL/Framebuffer.h index 9fee9e0fb..879ba11f1 100644 --- a/src/Magnum/GL/Framebuffer.h +++ b/src/Magnum/GL/Framebuffer.h @@ -85,8 +85,8 @@ macOS / iOS. In a deferred rendering setup for example, a shader usually has more than one output. That's finally where non-zero @ref ColorAttachment and @ref mapForDraw() gets used. In builtin shaders this is also how the -@ref Shaders::Flat::ColorOutput / @ref Shaders::Flat::ObjectIdOutput etc. get -used: +@ref Shaders::FlatGL::ColorOutput / @ref Shaders::FlatGL::ObjectIdOutput etc. +get used: @snippet MagnumGL.cpp Framebuffer-usage-deferred diff --git a/src/Magnum/GL/Mesh.h b/src/Magnum/GL/Mesh.h index e236b523c..ce5f329f5 100644 --- a/src/Magnum/GL/Mesh.h +++ b/src/Magnum/GL/Mesh.h @@ -697,7 +697,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { * buffer with 76 bytes of some other data at the beginning (possibly * material configuration) and then the interleaved vertex array. Each * vertex consists of a weight, position, texture coordinate and - * a normal. You want to draw it with @ref Shaders::Phong, but it + * a normal. You want to draw it with @ref Shaders::PhongGL, but it * accepts only a position and a normal, so you have to skip the weight * and the texture coordinate in each vertex: * diff --git a/src/Magnum/GL/Renderer.h b/src/Magnum/GL/Renderer.h index 64669b254..ec7433992 100644 --- a/src/Magnum/GL/Renderer.h +++ b/src/Magnum/GL/Renderer.h @@ -1674,9 +1674,10 @@ class MAGNUM_GL_EXPORT Renderer { * * Note that in 3D you need to sort and render transparent objects * back-to-front after all opaque objects in order for them to appear - * correctly. Alternatively, builtin shaders such as @ref Shaders::Flat - * or @ref Shaders::Phong support alpha masking, which works without - * alpha blending enabled and doesn't require depth sorting. + * correctly. Alternatively, builtin shaders such as + * @ref Shaders::FlatGL or @ref Shaders::PhongGL support alpha masking, + * which works without alpha blending enabled and doesn't require depth + * sorting. * @see @ref Feature::Blending, @ref setBlendFunction(BlendFunction, BlendFunction, BlendFunction, BlendFunction), * @ref setBlendEquation(), @ref setBlendColor(), * @fn_gl_keyword{BlendFunc} diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index 238afa9b9..1b911666a 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -674,7 +674,12 @@ template class Vector { T _data[size]; private: + #ifndef DOXYGEN_GENERATING_OUTPUT + /* Since I added deprecated aliases to Shaders::VectorGL, this FUCKING + DUMPSTER FIRE DOXYGEN CRAP thinks this refers to Shaders::Vector or + whatever fucking insane thing. WHAT THE FUCK. */ template friend class Vector; + #endif /* These three needed to access _data to speed up debug builds */ template friend class RectangularMatrix; template friend class Matrix; diff --git a/src/Magnum/MeshTools/Compile.cpp b/src/Magnum/MeshTools/Compile.cpp index 4326c417a..7dec471a3 100644 --- a/src/Magnum/MeshTools/Compile.cpp +++ b/src/Magnum/MeshTools/Compile.cpp @@ -48,7 +48,7 @@ /* This header is included only privately and doesn't introduce any linker dependency, thus it's completely safe */ -#include "Magnum/Shaders/Generic.h" +#include "Magnum/Shaders/GenericGL.h" namespace Magnum { namespace MeshTools { @@ -88,34 +88,34 @@ GL::Mesh compileInternal(const Trade::MeshData& meshData, GL::Buffer&& indices, case Trade::MeshAttribute::Position: /* Pick 3D position always, the format will properly reduce it to a 2-component version if needed */ - attribute.emplace(Shaders::Generic3D::Position{}, format); + attribute.emplace(Shaders::GenericGL3D::Position{}, format); break; case Trade::MeshAttribute::TextureCoordinates: /** @todo have Generic2D derived from Generic that has all attribute definitions common for 2D and 3D */ - attribute.emplace(Shaders::Generic2D::TextureCoordinates{}, format); + attribute.emplace(Shaders::GenericGL2D::TextureCoordinates{}, format); break; case Trade::MeshAttribute::Color: /** @todo have Generic2D derived from Generic that has all attribute definitions common for 2D and 3D */ /* Pick Color4 always, the format will properly reduce it to a 3-component version if needed */ - attribute.emplace(Shaders::Generic2D::Color4{}, format); + attribute.emplace(Shaders::GenericGL2D::Color4{}, format); break; case Trade::MeshAttribute::Tangent: /* Pick Tangent4 always, the format will properly reduce it to a 3-component version if needed */ - attribute.emplace(Shaders::Generic3D::Tangent4{}, format); + attribute.emplace(Shaders::GenericGL3D::Tangent4{}, format); break; case Trade::MeshAttribute::Bitangent: - attribute.emplace(Shaders::Generic3D::Bitangent{}, format); + attribute.emplace(Shaders::GenericGL3D::Bitangent{}, format); break; case Trade::MeshAttribute::Normal: - attribute.emplace(Shaders::Generic3D::Normal{}, format); + attribute.emplace(Shaders::GenericGL3D::Normal{}, format); break; #ifndef MAGNUM_TARGET_GLES2 case Trade::MeshAttribute::ObjectId: - attribute.emplace(Shaders::Generic3D::ObjectId{}, format); + attribute.emplace(Shaders::GenericGL3D::ObjectId{}, format); break; #endif diff --git a/src/Magnum/MeshTools/Compile.h b/src/Magnum/MeshTools/Compile.h index 0cea50534..ab53b02f0 100644 --- a/src/Magnum/MeshTools/Compile.h +++ b/src/Magnum/MeshTools/Compile.h @@ -95,22 +95,22 @@ typedef Containers::EnumSet CompileFlags; CORRADE_ENUMSET_OPERATORS(CompileFlags) /** -@brief Compile mesh data +@brief Compile OpenGL mesh data @m_since{2020,06} -Configures a mesh for a @ref Shaders::Generic shader with a vertex buffer and +Configures a mesh for a @ref Shaders::GenericGL shader with a vertex buffer and possibly also an index buffer, if the mesh is indexed. - If the mesh contains positions, these are bound to the - @ref Shaders::Generic2D::Position attribute if they are 2D or to - @ref Shaders::Generic3D::Position if they are 3D. + @ref Shaders::GenericGL2D::Position attribute if they are 2D or to + @ref Shaders::GenericGL3D::Position if they are 3D. - If the mesh contains normals or if @ref CompileFlag::GenerateFlatNormals / @ref CompileFlag::GenerateSmoothNormals is set, these are bound to - @ref Shaders::Generic3D::Normal. + @ref Shaders::GenericGL3D::Normal. - If the mesh contains texture coordinates, these are bound to - @ref Shaders::Generic::TextureCoordinates. + @ref Shaders::GenericGL::TextureCoordinates. - If the mesh contains colors, these are bound to - @ref Shaders::Generic::Color3 / @ref Shaders::Generic::Color4 based on + @ref Shaders::GenericGL::Color3 / @ref Shaders::GenericGL::Color4 based on their type. - Custom attributes and known attributes of implementation-specific types are ignored with a warning. See the @ref compile(const Trade::MeshData&, GL::Buffer&, GL::Buffer&) @@ -200,11 +200,11 @@ MAGNUM_MESHTOOLS_EXPORT GL::Mesh compile(const Trade::MeshData& meshData, GL::Bu @m_deprecated_since{2020,06} Use @ref compile(const Trade::MeshData&, CompileFlags) instead. -Configures a mesh for @ref Shaders::Generic2D shader with vertex buffer and +Configures a mesh for @ref Shaders::GenericGL2D shader with vertex buffer and possibly also an index buffer, if the mesh is indexed. Positions are bound to -@ref Shaders::Generic2D::Position attribute. If the mesh contains texture -coordinates, these are bound to @ref Shaders::Generic2D::TextureCoordinates -attribute. If the mesh contains colors, these are bound to @ref Shaders::Generic3D::Color4 +@ref Shaders::GenericGL2D::Position attribute. If the mesh contains texture +coordinates, these are bound to @ref Shaders::GenericGL2D::TextureCoordinates +attribute. If the mesh contains colors, these are bound to @ref Shaders::GenericGL3D::Color4 attribute. No data compression or index optimization (except for index buffer packing) is done, both the vertex buffer and the index buffer (if any) is owned by the mesh, both created with @ref GL::BufferUsage::StaticDraw. @@ -230,15 +230,16 @@ CORRADE_IGNORE_DEPRECATED_POP @m_deprecated_since{2020,06} Use @ref compile(const Trade::MeshData&, CompileFlags) instead. -Configures mesh for @ref Shaders::Generic3D shader with vertex buffer and +Configures mesh for @ref Shaders::GenericGL3D shader with vertex buffer and possibly also index buffer, if the mesh is indexed. Positions are bound to -@ref Shaders::Generic3D::Position attribute. If the mesh contains normals, they -are bound to @ref Shaders::Generic3D::Normal attribute, texture coordinates are -bound to @ref Shaders::Generic3D::TextureCoordinates attribute. If the mesh -contains colors, they are bound to @ref Shaders::Generic3D::Color4 attribute. -No data compression or index optimization (except for index buffer packing) is -done, both the vertex buffer and the index buffer (if any) is owned by the mesh, -both created with @ref GL::BufferUsage::StaticDraw. +@ref Shaders::GenericGL3D::Position attribute. If the mesh contains normals, +they are bound to @ref Shaders::GenericGL3D::Normal attribute, texture +coordinates are bound to @ref Shaders::GenericGL3D::TextureCoordinates +attribute. If the mesh contains colors, they are bound to +@ref Shaders::GenericGL3D::Color4 attribute. No data compression or index +optimization (except for index buffer packing) is done, both the vertex buffer +and the index buffer (if any) is owned by the mesh, both created with +@ref GL::BufferUsage::StaticDraw. This is just a convenience function for creating generic meshes, you might want to use @ref interleave() and @ref compressIndices() functions together with diff --git a/src/Magnum/MeshTools/Test/CompileGLTest.cpp b/src/Magnum/MeshTools/Test/CompileGLTest.cpp index ab7c939c0..c5838c51c 100644 --- a/src/Magnum/MeshTools/Test/CompileGLTest.cpp +++ b/src/Magnum/MeshTools/Test/CompileGLTest.cpp @@ -48,10 +48,10 @@ #include "Magnum/Math/Matrix4.h" #include "Magnum/MeshTools/Compile.h" #include "Magnum/MeshTools/Duplicate.h" -#include "Magnum/Shaders/Flat.h" -#include "Magnum/Shaders/Phong.h" -#include "Magnum/Shaders/VertexColor.h" -#include "Magnum/Shaders/MeshVisualizer.h" +#include "Magnum/Shaders/FlatGL.h" +#include "Magnum/Shaders/PhongGL.h" +#include "Magnum/Shaders/VertexColorGL.h" +#include "Magnum/Shaders/MeshVisualizerGL.h" #include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/MeshData.h" @@ -118,22 +118,22 @@ struct CompileGLTest: GL::OpenGLTester { private: PluginManager::Manager _manager{"nonexistent"}; - Shaders::Flat2D _flat2D; - Shaders::Flat2D _flatTextured2D{Shaders::Flat2D::Flag::Textured}; + Shaders::FlatGL2D _flat2D; + Shaders::FlatGL2D _flatTextured2D{Shaders::FlatGL2D::Flag::Textured}; #ifndef MAGNUM_TARGET_GLES2 - Shaders::Flat2D _flatObjectId2D{NoCreate}; + Shaders::FlatGL2D _flatObjectId2D{NoCreate}; #endif - Shaders::Flat3D _flat3D; - Shaders::Flat3D _flatTextured3D{Shaders::Flat3D::Flag::Textured}; + Shaders::FlatGL3D _flat3D; + Shaders::FlatGL3D _flatTextured3D{Shaders::FlatGL3D::Flag::Textured}; #ifndef MAGNUM_TARGET_GLES2 - Shaders::Flat3D _flatObjectId3D{NoCreate}; + Shaders::FlatGL3D _flatObjectId3D{NoCreate}; #endif - Shaders::VertexColor2D _color2D; - Shaders::VertexColor3D _color3D; - Shaders::Phong _phong; + Shaders::VertexColorGL2D _color2D; + Shaders::VertexColorGL3D _color3D; + Shaders::PhongGL _phong; #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - Shaders::MeshVisualizer3D _meshVisualizer3D{NoCreate}; - Shaders::MeshVisualizer3D _meshVisualizerBitangentsFromTangents3D{NoCreate}; + Shaders::MeshVisualizerGL3D _meshVisualizer3D{NoCreate}; + Shaders::MeshVisualizerGL3D _meshVisualizerBitangentsFromTangents3D{NoCreate}; #endif GL::Renderbuffer _color; @@ -315,14 +315,14 @@ CompileGLTest::CompileGLTest() { if(GL::Context::current().isExtensionSupported()) #endif { - _flatObjectId2D = Shaders::Flat2D{Shaders::Flat2D::Flag::InstancedObjectId}; - _flatObjectId3D = Shaders::Flat3D{Shaders::Flat3D::Flag::InstancedObjectId}; + _flatObjectId2D = Shaders::FlatGL2D{Shaders::FlatGL2D::Flag::InstancedObjectId}; + _flatObjectId3D = Shaders::FlatGL3D{Shaders::FlatGL3D::Flag::InstancedObjectId}; _objectId.setStorage(GL::RenderbufferFormat::R32UI, {32, 32}); _framebuffer .attachRenderbuffer(GL::Framebuffer::ColorAttachment{1}, _objectId) .mapForDraw({ - {Shaders::Generic3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, - {Shaders::Generic3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}} + {Shaders::GenericGL3D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, + {Shaders::GenericGL3D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}} }); } #endif @@ -335,14 +335,14 @@ CompileGLTest::CompileGLTest() { if(GL::Context::current().isExtensionSupported()) #endif { - _meshVisualizer3D = Shaders::MeshVisualizer3D{ - Shaders::MeshVisualizer3D::Flag::TangentDirection| - Shaders::MeshVisualizer3D::Flag::BitangentDirection| - Shaders::MeshVisualizer3D::Flag::NormalDirection}; - _meshVisualizerBitangentsFromTangents3D = Shaders::MeshVisualizer3D{ - Shaders::MeshVisualizer3D::Flag::TangentDirection| - Shaders::MeshVisualizer3D::Flag::BitangentFromTangentDirection| - Shaders::MeshVisualizer3D::Flag::NormalDirection}; + _meshVisualizer3D = Shaders::MeshVisualizerGL3D{ + Shaders::MeshVisualizerGL3D::Flag::TangentDirection| + Shaders::MeshVisualizerGL3D::Flag::BitangentDirection| + Shaders::MeshVisualizerGL3D::Flag::NormalDirection}; + _meshVisualizerBitangentsFromTangents3D = Shaders::MeshVisualizerGL3D{ + Shaders::MeshVisualizerGL3D::Flag::TangentDirection| + Shaders::MeshVisualizerGL3D::Flag::BitangentFromTangentDirection| + Shaders::MeshVisualizerGL3D::Flag::NormalDirection}; } #endif } diff --git a/src/Magnum/SceneGraph/Drawable.h b/src/Magnum/SceneGraph/Drawable.h index 4cacb2e22..f6f6603fc 100644 --- a/src/Magnum/SceneGraph/Drawable.h +++ b/src/Magnum/SceneGraph/Drawable.h @@ -55,8 +55,8 @@ by multiple objects, and pass only references around. The @p transformationMatrix parameter in the @ref draw() function contains transformation of the object (to which the drawable is attached) relative to @p camera. The camera contains the projection matrix. Some shaders (like the -@ref Shaders::Phong used in the snippet) have separate functions for setting -transformation and projection matrix, but some (such as @ref Shaders::Flat) +@ref Shaders::PhongGL used in the snippet) have separate functions for setting +transformation and projection matrix, but some (such as @ref Shaders::FlatGL) have a single function to set composite transformation and projection matrix. In that case you need to combine the two matrices manually like in the following code. Some shaders might have additional requirements, see their diff --git a/src/Magnum/Shaders/AbstractVector.h b/src/Magnum/Shaders/AbstractVector.h index 98fd36a38..192371879 100644 --- a/src/Magnum/Shaders/AbstractVector.h +++ b/src/Magnum/Shaders/AbstractVector.h @@ -25,94 +25,46 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file - * @brief Class @ref Magnum::Shaders::AbstractVector, typedef @ref Magnum::Shaders::AbstractVector2D, @ref Magnum::Shaders::AbstractVector3D + * @brief Typedef @ref Magnum::Shaders::AbstractVector, alias @ref Magnum::Shaders::AbstractVector2D, @ref Magnum::Shaders::AbstractVector3D + * @m_deprecated_since_latest Use @ref Magnum/Shaders/AbstractVectorGL.h, the + * @ref Magnum::Shaders::AbstractVectorGL "AbstractVectorGL" class and + * related typedefs instead. */ +#endif -#include "Magnum/GL/AbstractShaderProgram.h" -#include "Magnum/Shaders/Generic.h" - -namespace Magnum { namespace Shaders { - -/** -@brief Base for vector shaders - -See @ref DistanceFieldVector and @ref Vector for more information. -@see @ref shaders, @ref AbstractVector2D, @ref AbstractVector3D -*/ -template class AbstractVector: public GL::AbstractShaderProgram { - public: - /** - * @brief Vertex position - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector2 "Vector2" in 2D, @ref Magnum::Vector3 "Vector3" - * in 3D. - */ - typedef typename Generic::Position Position; - - /** - * @brief 2D texture coordinates - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector2 "Vector2". - */ - typedef typename Generic::TextureCoordinates TextureCoordinates; - - enum: UnsignedInt { - /** - * Color shader output. @ref shaders-generic "Generic output", - * present always. Expects three- or four-component floating-point - * or normalized buffer attachment. - */ - ColorOutput = Generic::ColorOutput - }; - - /** @brief Copying is not allowed */ - AbstractVector(const AbstractVector&) = delete; - - /** @brief Move constructor */ - AbstractVector(AbstractVector&&) noexcept = default; +#include "Magnum/configure.h" - /** @brief Copying is not allowed */ - AbstractVector& operator=(const AbstractVector&) = delete; +#ifdef MAGNUM_BUILD_DEPRECATED +#include - /** @brief Move assignment */ - AbstractVector& operator=(AbstractVector&&) noexcept = default; +#include "Magnum/Shaders/AbstractVectorGL.h" - /** - * @brief Bind vector texture - * @return Reference to self (for method chaining) - * - * @see @ref DistanceFieldVector::Flag::TextureTransformation, - * @ref Vector::Flag::TextureTransformation, - * @ref DistanceFieldVector::setTextureMatrix(), - * @ref Vector::setTextureMatrix() - */ - AbstractVector& bindVectorTexture(GL::Texture2D& texture); +CORRADE_DEPRECATED_FILE("use Magnum/Shaders/AbstractVectorGL.h, the AbstractVectorGL class and related typedefs instead") - #ifndef DOXYGEN_GENERATING_OUTPUT - protected: - #else - private: - #endif - /* Those textures are quite specific (and likely reused multiple times - per frame for e.g. text rendering, so put them in a specific slot. - Older iOS (and iOS WebGL) has only 8 texture units, so can't go - above that. Unit 7 is used by TextureTools::DistanceField. */ - enum: Int { VectorTextureUnit = 6 }; +namespace Magnum { namespace Shaders { - explicit AbstractVector(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - explicit AbstractVector() = default; - ~AbstractVector() = default; -}; +/** @brief @copybrief AbstractVectorGL + * @m_deprecated_since_latest Use @ref AbstractVectorGL instead. + */ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using AbstractVector CORRADE_DEPRECATED_ALIAS("use AbstractVectorGL instead") = AbstractVectorGL; +#endif -/** @brief Base for two-dimensional text shaders */ -typedef AbstractVector<2> AbstractVector2D; +/** @brief @copybrief AbstractVectorGL2D + * @m_deprecated_since_latest Use @ref AbstractVectorGL2D instead. + */ +typedef CORRADE_DEPRECATED("use AbstractVectorGL2D instead") AbstractVectorGL2D AbstractVector2D; -/** @brief Base for three-dimensional text shader */ -typedef AbstractVector<3> AbstractVector3D; +/** @brief @copybrief AbstractVectorGL3D + * @m_deprecated_since_latest Use @ref AbstractVectorGL3D instead. + */ +typedef CORRADE_DEPRECATED("use AbstractVectorGL3D instead") AbstractVectorGL3D AbstractVector3D; }} +#else +#error use Magnum/Shaders/AbstractVectorGL.h, the AbstractVectorGL class and related typedefs instead +#endif #endif diff --git a/src/Magnum/Shaders/AbstractVector.cpp b/src/Magnum/Shaders/AbstractVectorGL.cpp similarity index 83% rename from src/Magnum/Shaders/AbstractVector.cpp rename to src/Magnum/Shaders/AbstractVectorGL.cpp index 8361e1641..e02251094 100644 --- a/src/Magnum/Shaders/AbstractVector.cpp +++ b/src/Magnum/Shaders/AbstractVectorGL.cpp @@ -23,21 +23,21 @@ DEALINGS IN THE SOFTWARE. */ -#include "AbstractVector.h" +#include "AbstractVectorGL.h" #include "Magnum/GL/Texture.h" #include "Magnum/Shaders/visibility.h" namespace Magnum { namespace Shaders { -template AbstractVector& AbstractVector::bindVectorTexture(GL::Texture2D& texture) { +template AbstractVectorGL& AbstractVectorGL::bindVectorTexture(GL::Texture2D& texture) { texture.bind(VectorTextureUnit); return *this; } #ifndef DOXYGEN_GENERATING_OUTPUT -template class MAGNUM_SHADERS_EXPORT AbstractVector<2>; -template class MAGNUM_SHADERS_EXPORT AbstractVector<3>; +template class MAGNUM_SHADERS_EXPORT AbstractVectorGL<2>; +template class MAGNUM_SHADERS_EXPORT AbstractVectorGL<3>; #endif }} diff --git a/src/Magnum/Shaders/AbstractVectorGL.h b/src/Magnum/Shaders/AbstractVectorGL.h new file mode 100644 index 000000000..c6b8a0c01 --- /dev/null +++ b/src/Magnum/Shaders/AbstractVectorGL.h @@ -0,0 +1,126 @@ +#ifndef Magnum_Shaders_AbstractVectorGL_h +#define Magnum_Shaders_AbstractVectorGL_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Shaders::AbstractVectorGL, typedef @ref Magnum::Shaders::AbstractVectorGL2D, @ref Magnum::Shaders::AbstractVectorGL3D + * @m_since_latest + */ + +#include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/Shaders/GenericGL.h" + +namespace Magnum { namespace Shaders { + +/** +@brief Base for vector OpenGL shaders +@m_since_latest + +See @ref DistanceFieldVectorGL and @ref VectorGL for more information. +@see @ref shaders, @ref AbstractVectorGL2D, @ref AbstractVectorGL3D +*/ +template class AbstractVectorGL: public GL::AbstractShaderProgram { + public: + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector2 "Vector2" in 2D, @ref Magnum::Vector3 "Vector3" + * in 3D. + */ + typedef typename GenericGL::Position Position; + + /** + * @brief 2D texture coordinates + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector2 "Vector2". + */ + typedef typename GenericGL::TextureCoordinates TextureCoordinates; + + enum: UnsignedInt { + /** + * Color shader output. @ref shaders-generic "Generic output", + * present always. Expects three- or four-component floating-point + * or normalized buffer attachment. + */ + ColorOutput = GenericGL::ColorOutput + }; + + /** @brief Copying is not allowed */ + AbstractVectorGL(const AbstractVectorGL&) = delete; + + /** @brief Move constructor */ + AbstractVectorGL(AbstractVectorGL&&) noexcept = default; + + /** @brief Copying is not allowed */ + AbstractVectorGL& operator=(const AbstractVectorGL&) = delete; + + /** @brief Move assignment */ + AbstractVectorGL& operator=(AbstractVectorGL&&) noexcept = default; + + /** + * @brief Bind vector texture + * @return Reference to self (for method chaining) + * + * @see @ref DistanceFieldVectorGL::Flag::TextureTransformation, + * @ref VectorGL::Flag::TextureTransformation, + * @ref DistanceFieldVectorGL::setTextureMatrix(), + * @ref VectorGL::setTextureMatrix() + */ + AbstractVectorGL& bindVectorTexture(GL::Texture2D& texture); + + #ifndef DOXYGEN_GENERATING_OUTPUT + protected: + #else + private: + #endif + /* Those textures are quite specific (and likely reused multiple times + per frame for e.g. text rendering, so put them in a specific slot. + Older iOS (and iOS WebGL) has only 8 texture units, so can't go + above that. Unit 7 is used by TextureTools::DistanceField. */ + enum: Int { VectorTextureUnit = 6 }; + + explicit AbstractVectorGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} + explicit AbstractVectorGL() = default; + ~AbstractVectorGL() = default; +}; + +/** +@brief Base for two-dimensional vector OpenGL shaders +@m_since_latest +*/ +typedef AbstractVectorGL<2> AbstractVectorGL2D; + +/** +@brief Base for three-dimensional vector OpenGL shader +@m_since_latest +*/ +typedef AbstractVectorGL<3> AbstractVectorGL3D; + +}} + +#endif diff --git a/src/Magnum/Shaders/CMakeLists.txt b/src/Magnum/Shaders/CMakeLists.txt index 3a940b774..b5b55947b 100644 --- a/src/Magnum/Shaders/CMakeLists.txt +++ b/src/Magnum/Shaders/CMakeLists.txt @@ -27,35 +27,47 @@ if(NOT WITH_GL) message(SEND_ERROR "Shaders are available only if WITH_GL is enabled") endif() -corrade_add_resource(MagnumShaders_RCS resources.conf) -set_target_properties(MagnumShaders_RCS-dependencies PROPERTIES FOLDER "Magnum/Shaders") +corrade_add_resource(MagnumShaders_RESOURCES_GL resources-gl.conf) +set_target_properties(MagnumShaders_RESOURCES_GL-dependencies PROPERTIES FOLDER "Magnum/Shaders") set(MagnumShaders_SRCS - AbstractVector.cpp - VertexColor.cpp + AbstractVectorGL.cpp + VertexColorGL.cpp - ${MagnumShaders_RCS}) + ${MagnumShaders_RESOURCES_GL}) set(MagnumShaders_GracefulAssert_SRCS - DistanceFieldVector.cpp - Flat.cpp - MeshVisualizer.cpp - Phong.cpp - Vector.cpp) + DistanceFieldVectorGL.cpp + FlatGL.cpp + MeshVisualizerGL.cpp + PhongGL.cpp + VectorGL.cpp) set(MagnumShaders_HEADERS - DistanceFieldVector.h - AbstractVector.h - Flat.h - Generic.h - MeshVisualizer.h - Phong.h + DistanceFieldVectorGL.h + AbstractVectorGL.h + FlatGL.h + GenericGL.h + MeshVisualizerGL.h + PhongGL.h Shaders.h - Vector.h - VertexColor.h + VectorGL.h + VertexColorGL.h visibility.h) +if(MAGNUM_BUILD_DEPRECATED) + list(APPEND MagnumShaders_HEADERS + DistanceFieldVector.h + AbstractVector.h + Flat.h + Generic.h + MeshVisualizer.h + Phong.h + Vector.h + VertexColor.h) +endif() + # Header files to display in project view of IDEs only set(MagnumShaders_PRIVATE_HEADERS Implementation/CreateCompatibilityShader.h) diff --git a/src/Magnum/Shaders/DistanceFieldVector.h b/src/Magnum/Shaders/DistanceFieldVector.h index a64eca957..c3b15183c 100644 --- a/src/Magnum/Shaders/DistanceFieldVector.h +++ b/src/Magnum/Shaders/DistanceFieldVector.h @@ -25,243 +25,46 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file - * @brief Class @ref Magnum::Shaders::DistanceFieldVector, typedef @ref Magnum::Shaders::DistanceFieldVector2D, @ref Magnum::Shaders::DistanceFieldVector3D + * @brief Typedef @ref Magnum::Shaders::DistanceFieldVector, alias @ref Magnum::Shaders::DistanceFieldVector2D, @ref Magnum::Shaders::DistanceFieldVector3D + * @m_deprecated_since_latest Use @ref Magnum/Shaders/DistanceFieldVectorGL.h, + * the @ref Magnum::Shaders::DistanceFieldVectorGL "DistanceFieldVectorGL" + * class and related typedefs instead. */ +#endif -#include "Magnum/DimensionTraits.h" -#include "Magnum/Shaders/AbstractVector.h" -#include "Magnum/Shaders/visibility.h" - -namespace Magnum { namespace Shaders { - -namespace Implementation { - enum class DistanceFieldVectorFlag: UnsignedByte { - TextureTransformation = 1 << 0 - }; - typedef Containers::EnumSet DistanceFieldVectorFlags; -} - -/** -@brief Distance field vector shader - -Renders vector graphics in a form of signed distance field. See -@ref TextureTools::DistanceField for more information. Note that the final -rendered outlook will greatly depend on radius of input distance field and -value passed to @ref setSmoothness(). You need to provide @ref Position and -@ref TextureCoordinates attributes in your triangle mesh and call at least -@ref bindVectorTexture(). By default, the shader renders the distance field -texture with a white color in an identity transformation, use -@ref setTransformationProjectionMatrix(), @ref setColor() and others to -configure the shader. - -Alpha / transparency is supported by the shader implicitly, but to have it -working on the framebuffer, you need to enable -@ref GL::Renderer::Feature::Blending and set up the blending function. See -@ref GL::Renderer::setBlendFunction() for details. - -@image html shaders-distancefieldvector.png width=256px - -@section Shaders-DistanceFieldVector-usage Example usage - -Common mesh setup: - -@snippet MagnumShaders.cpp DistanceFieldVector-usage1 - -Common rendering setup: - -@snippet MagnumShaders.cpp DistanceFieldVector-usage2 - -@see @ref shaders, @ref DistanceFieldVector2D, @ref DistanceFieldVector3D -@todo Use fragment shader derivations to have proper smoothness in perspective/ - large zoom levels, make it optional as it might have negative performance - impact -*/ -template class MAGNUM_SHADERS_EXPORT DistanceFieldVector: public AbstractVector { - public: - #ifdef DOXYGEN_GENERATING_OUTPUT - /** - * @brief Flag - * @m_since{2020,06} - * - * @see @ref Flags, @ref flags() - */ - enum class Flag: UnsignedByte { - /** - * Enable texture coordinate transformation. - * @see @ref setTextureMatrix() - * @m_since{2020,06} - */ - TextureTransformation = 1 << 0 - }; - - /** - * @brief Flags - * @m_since{2020,06} - * - * @see @ref flags() - */ - typedef Containers::EnumSet Flags; - #else - /* Done this way to be prepared for possible future diversion of 2D - and 3D flags (e.g. introducing 3D-specific features) */ - typedef Implementation::DistanceFieldVectorFlag Flag; - typedef Implementation::DistanceFieldVectorFlags Flags; - #endif - - /** - * @brief Constructor - * @param flags Flags - */ - explicit DistanceFieldVector(Flags flags = {}); - - /** - * @brief Construct without creating the underlying OpenGL object - * - * The constructed instance is equivalent to a moved-from state. Useful - * in cases where you will overwrite the instance later anyway. Move - * another object over it to make it useful. - * - * This function can be safely used for constructing (and later - * destructing) objects even without any OpenGL context being active. - * However note that this is a low-level and a potentially dangerous - * API, see the documentation of @ref NoCreate for alternatives. - */ - explicit DistanceFieldVector(NoCreateT) noexcept - /** @todoc remove workaround when doxygen is sane */ - #ifndef DOXYGEN_GENERATING_OUTPUT - : AbstractVector{NoCreate} - #endif - {} - - /** @brief Copying is not allowed */ - DistanceFieldVector(const DistanceFieldVector&) = delete; - - /** @brief Move constructor */ - DistanceFieldVector(DistanceFieldVector&&) noexcept = default; - - /** @brief Copying is not allowed */ - DistanceFieldVector& operator=(const DistanceFieldVector&) = delete; - - /** @brief Move assignment */ - DistanceFieldVector& operator=(DistanceFieldVector&&) noexcept = default; - - /** - * @brief Flags - * @m_since{2020,06} - */ - Flags flags() const { return _flags; } - - /** - * @brief Set transformation and projection matrix - * @return Reference to self (for method chaining) - * - * Initial value is an identity matrix. - */ - DistanceFieldVector& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); - - /** - * @brief Set texture coordinate transformation matrix - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * Expects that the shader was created with - * @ref Flag::TextureTransformation enabled. Initial value is an - * identity matrix. - */ - DistanceFieldVector& setTextureMatrix(const Matrix3& matrix); - - /** - * @brief Set fill color - * @return Reference to self (for method chaining) - * - * Initial value is @cpp 0xffffffff_rgbaf @ce. - * @see @ref setOutlineColor() - */ - DistanceFieldVector& setColor(const Color4& color); - - /** - * @brief Set outline color - * @return Reference to self (for method chaining) - * - * Initial value is @cpp 0x00000000_rgbaf @ce and the outline is not - * drawn --- see @ref setOutlineRange() for more information. - * @see @ref setOutlineRange(), @ref setColor() - */ - DistanceFieldVector& setOutlineColor(const Color4& color); - - /** - * @brief Set outline range - * @return Reference to self (for method chaining) - * - * The @p start parameter describes where fill ends and possible - * outline starts. Initial value is @cpp 0.5f @ce, larger values will - * make the vector art look thinner, smaller will make it look thicker. - * - * The @p end parameter describes where outline ends. If set to value - * larger than @p start the outline is not drawn. Initial value is - * @cpp 1.0f @ce. - * - * @see @ref setOutlineColor() - */ - DistanceFieldVector& setOutlineRange(Float start, Float end); +#include "Magnum/configure.h" - /** - * @brief Set smoothness radius - * @return Reference to self (for method chaining) - * - * Larger values will make edges look less aliased (but blurry), - * smaller values will make them look more crisp (but possibly - * aliased). Initial value is @cpp 0.04f @ce. - */ - DistanceFieldVector& setSmoothness(Float value); +#ifdef MAGNUM_BUILD_DEPRECATED +#include - #ifndef DOXYGEN_GENERATING_OUTPUT - /* Overloads to remove WTF-factor from method chaining order */ - DistanceFieldVector& bindVectorTexture(GL::Texture2D& texture) { - AbstractVector::bindVectorTexture(texture); - return *this; - } - #endif +#include "Magnum/Shaders/DistanceFieldVectorGL.h" - private: - /* Prevent accidentally calling irrelevant functions */ - #ifndef MAGNUM_TARGET_GLES - using GL::AbstractShaderProgram::drawTransformFeedback; - #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - using GL::AbstractShaderProgram::dispatchCompute; - #endif +CORRADE_DEPRECATED_FILE("use Magnum/Shaders/DistanceFieldVectorGL.h, the DistanceFieldVectorGL class and related typedefs instead") - Flags _flags; - Int _transformationProjectionMatrixUniform{0}, - _textureMatrixUniform{1}, - _colorUniform{2}, - _outlineColorUniform{3}, - _outlineRangeUniform{4}, - _smoothnessUniform{5}; -}; +namespace Magnum { namespace Shaders { -/** @brief Two-dimensional distance field vector shader */ -typedef DistanceFieldVector<2> DistanceFieldVector2D; +/** @brief @copybrief DistanceFieldVectorGL + * @m_deprecated_since_latest Use @ref DistanceFieldVectorGL instead. + */ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using DistanceFieldVector CORRADE_DEPRECATED_ALIAS("use DistanceFieldVectorGL instead") = DistanceFieldVectorGL; +#endif -/** @brief Three-dimensional distance field vector shader */ -typedef DistanceFieldVector<3> DistanceFieldVector3D; +/** @brief @copybrief DistanceFieldVectorGL2D + * @m_deprecated_since_latest Use @ref DistanceFieldVectorGL2D instead. + */ +typedef CORRADE_DEPRECATED("use DistanceFieldVectorGL2D instead") DistanceFieldVectorGL2D DistanceFieldVector2D; -#ifdef DOXYGEN_GENERATING_OUTPUT -/** @debugoperatorclassenum{DistanceFieldVector,DistanceFieldVector::Flag} */ -template Debug& operator<<(Debug& debug, DistanceFieldVector::Flag value); +/** @brief @copybrief DistanceFieldVectorGL3D + * @m_deprecated_since_latest Use @ref DistanceFieldVectorGL3D instead. + */ +typedef CORRADE_DEPRECATED("use DistanceFieldVectorGL3D instead") DistanceFieldVectorGL3D DistanceFieldVector3D; -/** @debugoperatorclassenum{DistanceFieldVector,DistanceFieldVector::Flags} */ -template Debug& operator<<(Debug& debug, DistanceFieldVector::Flags value); +}} #else -namespace Implementation { - MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, DistanceFieldVectorFlag value); - MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, DistanceFieldVectorFlags value); - CORRADE_ENUMSET_OPERATORS(DistanceFieldVectorFlags) -} +#error use Magnum/Shaders/DistanceFieldVectorGL.h, the DistanceFieldVectorGL class and related typedefs instead #endif -}} - #endif diff --git a/src/Magnum/Shaders/DistanceFieldVector.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp similarity index 75% rename from src/Magnum/Shaders/DistanceFieldVector.cpp rename to src/Magnum/Shaders/DistanceFieldVectorGL.cpp index ca34c98bc..19c50301f 100644 --- a/src/Magnum/Shaders/DistanceFieldVector.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "DistanceFieldVector.h" +#include "DistanceFieldVectorGL.h" #include #include @@ -40,13 +40,13 @@ namespace Magnum { namespace Shaders { -template DistanceFieldVector::DistanceFieldVector(const Flags flags): _flags{flags} { +template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags): _flags{flags} { #ifdef MAGNUM_BUILD_STATIC /* Import resources on static build, if not already */ - if(!Utility::Resource::hasGroup("MagnumShaders")) + if(!Utility::Resource::hasGroup("MagnumShadersGL")) importShaderResources(); #endif - Utility::Resource rs("MagnumShaders"); + Utility::Resource rs("MagnumShadersGL"); #ifndef MAGNUM_TARGET_GLES const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); @@ -74,8 +74,8 @@ template DistanceFieldVector::DistanceFieldV if(!GL::Context::current().isExtensionSupported(version)) #endif { - GL::AbstractShaderProgram::bindAttributeLocation(AbstractVector::Position::Location, "position"); - GL::AbstractShaderProgram::bindAttributeLocation(AbstractVector::TextureCoordinates::Location, "textureCoordinates"); + GL::AbstractShaderProgram::bindAttributeLocation(AbstractVectorGL::Position::Location, "position"); + GL::AbstractShaderProgram::bindAttributeLocation(AbstractVectorGL::TextureCoordinates::Location, "textureCoordinates"); } #endif @@ -99,7 +99,7 @@ template DistanceFieldVector::DistanceFieldV #endif { GL::AbstractShaderProgram::setUniform(GL::AbstractShaderProgram::uniformLocation("vectorTexture"), - AbstractVector::VectorTextureUnit); + AbstractVectorGL::VectorTextureUnit); } /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ @@ -113,49 +113,49 @@ template DistanceFieldVector::DistanceFieldV #endif } -template DistanceFieldVector& DistanceFieldVector::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { +template DistanceFieldVectorGL& DistanceFieldVectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { GL::AbstractShaderProgram::setUniform(_transformationProjectionMatrixUniform, matrix); return *this; } -template DistanceFieldVector& DistanceFieldVector::setTextureMatrix(const Matrix3& matrix) { +template DistanceFieldVectorGL& DistanceFieldVectorGL::setTextureMatrix(const Matrix3& matrix) { CORRADE_ASSERT(_flags & Flag::TextureTransformation, - "Shaders::DistanceFieldVector::setTextureMatrix(): the shader was not created with texture transformation enabled", *this); + "Shaders::DistanceFieldVectorGL::setTextureMatrix(): the shader was not created with texture transformation enabled", *this); GL::AbstractShaderProgram::setUniform(_textureMatrixUniform, matrix); return *this; } -template DistanceFieldVector& DistanceFieldVector::setColor(const Color4& color) { +template DistanceFieldVectorGL& DistanceFieldVectorGL::setColor(const Color4& color) { GL::AbstractShaderProgram::setUniform(_colorUniform, color); return *this; } -template DistanceFieldVector& DistanceFieldVector::setOutlineColor(const Color4& color) { +template DistanceFieldVectorGL& DistanceFieldVectorGL::setOutlineColor(const Color4& color) { GL::AbstractShaderProgram::setUniform(_outlineColorUniform, color); return *this; } -template DistanceFieldVector& DistanceFieldVector::setOutlineRange(Float start, Float end) { +template DistanceFieldVectorGL& DistanceFieldVectorGL::setOutlineRange(Float start, Float end) { GL::AbstractShaderProgram::setUniform(_outlineRangeUniform, Vector2(start, end)); return *this; } -template DistanceFieldVector& DistanceFieldVector::setSmoothness(Float value) { +template DistanceFieldVectorGL& DistanceFieldVectorGL::setSmoothness(Float value) { GL::AbstractShaderProgram::setUniform(_smoothnessUniform, value); return *this; } -template class DistanceFieldVector<2>; -template class DistanceFieldVector<3>; +template class DistanceFieldVectorGL<2>; +template class DistanceFieldVectorGL<3>; namespace Implementation { -Debug& operator<<(Debug& debug, const DistanceFieldVectorFlag value) { - debug << "Shaders::DistanceFieldVector::Flag" << Debug::nospace; +Debug& operator<<(Debug& debug, const DistanceFieldVectorGLFlag value) { + debug << "Shaders::DistanceFieldVectorGL::Flag" << Debug::nospace; switch(value) { /* LCOV_EXCL_START */ - #define _c(v) case DistanceFieldVectorFlag::v: return debug << "::" #v; + #define _c(v) case DistanceFieldVectorGLFlag::v: return debug << "::" #v; _c(TextureTransformation) #undef _c /* LCOV_EXCL_STOP */ @@ -164,9 +164,9 @@ Debug& operator<<(Debug& debug, const DistanceFieldVectorFlag value) { return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } -Debug& operator<<(Debug& debug, const DistanceFieldVectorFlags value) { - return Containers::enumSetDebugOutput(debug, value, "Shaders::DistanceFieldVector::Flags{}", { - DistanceFieldVectorFlag::TextureTransformation +Debug& operator<<(Debug& debug, const DistanceFieldVectorGLFlags value) { + return Containers::enumSetDebugOutput(debug, value, "Shaders::DistanceFieldVectorGL::Flags{}", { + DistanceFieldVectorGLFlag::TextureTransformation }); } diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.h b/src/Magnum/Shaders/DistanceFieldVectorGL.h new file mode 100644 index 000000000..92ede2175 --- /dev/null +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.h @@ -0,0 +1,275 @@ +#ifndef Magnum_Shaders_DistanceFieldVectorGL_h +#define Magnum_Shaders_DistanceFieldVectorGL_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Shaders::DistanceFieldVectorGL, typedef @ref Magnum::Shaders::DistanceFieldVectorGL2D, @ref Magnum::Shaders::DistanceFieldVectorGL3D + * @m_since_latest + */ + +#include "Magnum/DimensionTraits.h" +#include "Magnum/Shaders/AbstractVectorGL.h" +#include "Magnum/Shaders/visibility.h" + +namespace Magnum { namespace Shaders { + +namespace Implementation { + enum class DistanceFieldVectorGLFlag: UnsignedByte { + TextureTransformation = 1 << 0 + }; + typedef Containers::EnumSet DistanceFieldVectorGLFlags; +} + +/** +@brief Distance field vector OpenGL shader +@m_since_latest + +Renders vector graphics in a form of signed distance field. See +@ref TextureTools::DistanceField for more information. Note that the final +rendered outlook will greatly depend on radius of input distance field and +value passed to @ref setSmoothness(). You need to provide @ref Position and +@ref TextureCoordinates attributes in your triangle mesh and call at least +@ref bindVectorTexture(). By default, the shader renders the distance field +texture with a white color in an identity transformation, use +@ref setTransformationProjectionMatrix(), @ref setColor() and others to +configure the shader. + +Alpha / transparency is supported by the shader implicitly, but to have it +working on the framebuffer, you need to enable +@ref GL::Renderer::Feature::Blending and set up the blending function. See +@ref GL::Renderer::setBlendFunction() for details. + +@image html shaders-distancefieldvector.png width=256px + +@section Shaders-DistanceFieldVectorGL-usage Example usage + +Common mesh setup: + +@snippet MagnumShaders-gl.cpp DistanceFieldVectorGL-usage1 + +Common rendering setup: + +@snippet MagnumShaders-gl.cpp DistanceFieldVectorGL-usage2 + +@see @ref shaders, @ref DistanceFieldVectorGL2D, @ref DistanceFieldVectorGL3D +@todo Use fragment shader derivations to have proper smoothness in perspective/ + large zoom levels, make it optional as it might have negative performance + impact +*/ +template class MAGNUM_SHADERS_EXPORT DistanceFieldVectorGL: public AbstractVectorGL { + public: + #ifdef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Flag + * @m_since{2020,06} + * + * @see @ref Flags, @ref flags() + */ + enum class Flag: UnsignedByte { + /** + * Enable texture coordinate transformation. + * @see @ref setTextureMatrix() + * @m_since{2020,06} + */ + TextureTransformation = 1 << 0 + }; + + /** + * @brief Flags + * @m_since{2020,06} + * + * @see @ref flags() + */ + typedef Containers::EnumSet Flags; + #else + /* Done this way to be prepared for possible future diversion of 2D + and 3D flags (e.g. introducing 3D-specific features) */ + typedef Implementation::DistanceFieldVectorGLFlag Flag; + typedef Implementation::DistanceFieldVectorGLFlags Flags; + #endif + + /** + * @brief Constructor + * @param flags Flags + */ + explicit DistanceFieldVectorGL(Flags flags = {}); + + /** + * @brief Construct without creating the underlying OpenGL object + * + * The constructed instance is equivalent to a moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit DistanceFieldVectorGL(NoCreateT) noexcept + /** @todoc remove workaround when doxygen is sane */ + #ifndef DOXYGEN_GENERATING_OUTPUT + : AbstractVectorGL{NoCreate} + #endif + {} + + /** @brief Copying is not allowed */ + DistanceFieldVectorGL(const DistanceFieldVectorGL&) = delete; + + /** @brief Move constructor */ + DistanceFieldVectorGL(DistanceFieldVectorGL&&) noexcept = default; + + /** @brief Copying is not allowed */ + DistanceFieldVectorGL& operator=(const DistanceFieldVectorGL&) = delete; + + /** @brief Move assignment */ + DistanceFieldVectorGL& operator=(DistanceFieldVectorGL&&) noexcept = default; + + /** + * @brief Flags + * @m_since{2020,06} + */ + Flags flags() const { return _flags; } + + /** + * @brief Set transformation and projection matrix + * @return Reference to self (for method chaining) + * + * Initial value is an identity matrix. + */ + DistanceFieldVectorGL& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); + + /** + * @brief Set texture coordinate transformation matrix + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * Expects that the shader was created with + * @ref Flag::TextureTransformation enabled. Initial value is an + * identity matrix. + */ + DistanceFieldVectorGL& setTextureMatrix(const Matrix3& matrix); + + /** + * @brief Set fill color + * @return Reference to self (for method chaining) + * + * Initial value is @cpp 0xffffffff_rgbaf @ce. + * @see @ref setOutlineColor() + */ + DistanceFieldVectorGL& setColor(const Color4& color); + + /** + * @brief Set outline color + * @return Reference to self (for method chaining) + * + * Initial value is @cpp 0x00000000_rgbaf @ce and the outline is not + * drawn --- see @ref setOutlineRange() for more information. + * @see @ref setOutlineRange(), @ref setColor() + */ + DistanceFieldVectorGL& setOutlineColor(const Color4& color); + + /** + * @brief Set outline range + * @return Reference to self (for method chaining) + * + * The @p start parameter describes where fill ends and possible + * outline starts. Initial value is @cpp 0.5f @ce, larger values will + * make the vector art look thinner, smaller will make it look thicker. + * + * The @p end parameter describes where outline ends. If set to value + * larger than @p start the outline is not drawn. Initial value is + * @cpp 1.0f @ce. + * + * @see @ref setOutlineColor() + */ + DistanceFieldVectorGL& setOutlineRange(Float start, Float end); + + /** + * @brief Set smoothness radius + * @return Reference to self (for method chaining) + * + * Larger values will make edges look less aliased (but blurry), + * smaller values will make them look more crisp (but possibly + * aliased). Initial value is @cpp 0.04f @ce. + */ + DistanceFieldVectorGL& setSmoothness(Float value); + + #ifndef DOXYGEN_GENERATING_OUTPUT + /* Overloads to remove WTF-factor from method chaining order */ + DistanceFieldVectorGL& bindVectorTexture(GL::Texture2D& texture) { + AbstractVectorGL::bindVectorTexture(texture); + return *this; + } + #endif + + private: + /* Prevent accidentally calling irrelevant functions */ + #ifndef MAGNUM_TARGET_GLES + using GL::AbstractShaderProgram::drawTransformFeedback; + #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + using GL::AbstractShaderProgram::dispatchCompute; + #endif + + Flags _flags; + Int _transformationProjectionMatrixUniform{0}, + _textureMatrixUniform{1}, + _colorUniform{2}, + _outlineColorUniform{3}, + _outlineRangeUniform{4}, + _smoothnessUniform{5}; +}; + +/** +@brief Two-dimensional distance field vector OpenGL shader +@m_since_latest +*/ +typedef DistanceFieldVectorGL<2> DistanceFieldVectorGL2D; + +/** +@brief Three-dimensional distance field vector OpenGL shader +@m_since_latest +*/ +typedef DistanceFieldVectorGL<3> DistanceFieldVectorGL3D; + +#ifdef DOXYGEN_GENERATING_OUTPUT +/** @debugoperatorclassenum{DistanceFieldVectorGL,DistanceFieldVectorGL::Flag} */ +template Debug& operator<<(Debug& debug, DistanceFieldVector::Flag value); + +/** @debugoperatorclassenum{DistanceFieldVectorGL,DistanceFieldVectorGL::Flags} */ +template Debug& operator<<(Debug& debug, DistanceFieldVector::Flags value); +#else +namespace Implementation { + MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, DistanceFieldVectorGLFlag value); + MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, DistanceFieldVectorGLFlags value); + CORRADE_ENUMSET_OPERATORS(DistanceFieldVectorGLFlags) +} +#endif + +}} + +#endif diff --git a/src/Magnum/Shaders/Flat.h b/src/Magnum/Shaders/Flat.h index 1a5d4ab0a..70311e465 100644 --- a/src/Magnum/Shaders/Flat.h +++ b/src/Magnum/Shaders/Flat.h @@ -25,507 +25,46 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file - * @brief Class @ref Magnum::Shaders::Flat, typedef @ref Magnum::Shaders::Flat2D, @ref Magnum::Shaders::Flat3D + * @brief Typedef @ref Magnum::Shaders::Flat, alias @ref Magnum::Shaders::Flat2D, @ref Magnum::Shaders::Flat3D + * @m_deprecated_since_latest Use @ref Magnum/Shaders/FlatGL.h, the + * @ref Magnum::Shaders::FlatGL "FlatGL" class and + * related typedefs instead. */ +#endif -#include "Magnum/DimensionTraits.h" -#include "Magnum/GL/AbstractShaderProgram.h" -#include "Magnum/Shaders/Generic.h" -#include "Magnum/Shaders/visibility.h" - -namespace Magnum { namespace Shaders { - -namespace Implementation { - enum class FlatFlag: UnsignedByte { - Textured = 1 << 0, - AlphaMask = 1 << 1, - VertexColor = 1 << 2, - TextureTransformation = 1 << 3, - #ifndef MAGNUM_TARGET_GLES2 - ObjectId = 1 << 4, - InstancedObjectId = (1 << 5)|ObjectId, - #endif - InstancedTransformation = 1 << 6, - InstancedTextureOffset = (1 << 7)|TextureTransformation - }; - typedef Containers::EnumSet FlatFlags; -} - -/** -@brief Flat shader - -Draws the whole mesh with given color or texture. For a colored mesh you need -to provide the @ref Position attribute in your triangle mesh. By default, the -shader renders the mesh with a white color in an identity transformation. -Use @ref setTransformationProjectionMatrix(), @ref setColor() and others to -configure the shader. - -@image html shaders-flat.png width=256px - -@section Shaders-Flat-colored Colored rendering - -Common mesh setup: - -@snippet MagnumShaders.cpp Flat-usage-colored1 - -Common rendering setup: - -@snippet MagnumShaders.cpp Flat-usage-colored2 - -@section Shaders-Flat-textured Textured rendering - -If you want to use a texture, you need to provide also the -@ref TextureCoordinates attribute. Pass @ref Flag::Textured to the constructor -and then at render time don't forget to bind also the texture via -@ref bindTexture(). The texture is multipled by the color, which is by default -set to @cpp 0xffffffff_rgbaf @ce. Common mesh setup: - -@snippet MagnumShaders.cpp Flat-usage-textured1 - -Common rendering setup: - -@snippet MagnumShaders.cpp Flat-usage-textured2 - -For coloring the texture based on intensity you can use the @ref Vector shader. -The 3D version of this shader is equivalent to @ref Phong with zero lights, -however this implementation is much simpler and thus likely also faster. See -@ref Shaders-Phong-lights-zero "its documentation" for more information. -Conversely, enabling @ref Flag::VertexColor and using a default color with no -texturing makes this shader equivalent to @ref VertexColor. - -@section Shaders-Flat-alpha Alpha blending and masking - -Alpha / transparency is supported by the shader implicitly, but to have it -working on the framebuffer, you need to enable -@ref GL::Renderer::Feature::Blending and set up the blending function. See -@ref GL::Renderer::setBlendFunction() for details. - -An alternative is to enable @ref Flag::AlphaMask and tune @ref setAlphaMask() -for simple binary alpha-masked drawing that doesn't require depth sorting or -blending enabled. Note that this feature is implemented using the GLSL -@glsl discard @ce operation which is known to have considerable performance -impact on some platforms. With proper depth sorting and blending you'll usually -get much better performance and output quality. - -@section Shaders-Flat-object-id Object ID output - -The shader supports writing object ID to the framebuffer for object picking or -other annotation purposes. Enable it using @ref Flag::ObjectId and set up an -integer buffer attached to the @ref ObjectIdOutput attachment. Note that for -portability you should use @ref GL::Framebuffer::clearColor() instead of -@ref GL::Framebuffer::clear() as the former usually emits GL errors when called -on framebuffers with integer attachments. - -@snippet MagnumShaders.cpp Flat-usage-object-id - -If you have a batch of meshes with different object IDs, enable -@ref Flag::InstancedObjectId and supply per-vertex IDs to the @ref ObjectId -attribute. The output will contain a sum of the per-vertex ID and ID coming -from @ref setObjectId(). - -@requires_gles30 Object ID output requires integer buffer attachments, which - are not available in OpenGL ES 2.0 or WebGL 1.0. - -@section Shaders-Flat-instancing Instanced rendering - -Enabling @ref Flag::InstancedTransformation will turn the shader into an -instanced one. It'll take per-instance transformation from the -@ref TransformationMatrix attribute, applying it before the matrix set by -@ref setTransformationProjectionMatrix(). Besides that, @ref Flag::VertexColor -(and the @ref Color3 / @ref Color4) attributes can work as both per-vertex and -per-instance, and for texturing it's possible to have per-instance texture -offset taken from @ref TextureOffset when @ref Flag::InstancedTextureOffset is -enabled (similarly to transformation, applied before @ref setTextureMatrix()). -The snippet below shows adding a buffer with per-instance transformation and -color to a mesh: - -@snippet MagnumShaders.cpp Flat-usage-instancing - -@requires_gl33 Extension @gl_extension{ARB,instanced_arrays} -@requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - @gl_extension{EXT,instanced_arrays} or @gl_extension{NV,instanced_arrays} - in OpenGL ES 2.0. -@requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} in WebGL - 1.0. - -@see @ref shaders, @ref Flat2D, @ref Flat3D -*/ -template class MAGNUM_SHADERS_EXPORT Flat: public GL::AbstractShaderProgram { - public: - /** - * @brief Vertex position - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector2 "Vector2" in 2D, @ref Magnum::Vector3 "Vector3" - * in 3D. - */ - typedef typename Generic::Position Position; - - /** - * @brief 2D texture coordinates - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector2 "Vector2". Used only if @ref Flag::Textured is - * set. - */ - typedef typename Generic::TextureCoordinates TextureCoordinates; - - /** - * @brief Three-component vertex color - * @m_since{2019,10} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Color3. Use - * either this or the @ref Color4 attribute. Used only if - * @ref Flag::VertexColor is set. - */ - typedef typename Generic::Color3 Color3; - - /** - * @brief Four-component vertex color - * @m_since{2019,10} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Color4. Use - * either this or the @ref Color3 attribute. Used only if - * @ref Flag::VertexColor is set. - */ - typedef typename Generic::Color4 Color4; - - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief (Instanced) object ID - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. - * Used only if @ref Flag::InstancedObjectId is set. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. - */ - typedef typename Generic::ObjectId ObjectId; - #endif - - /** - * @brief (Instanced) transformation matrix - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Matrix3 in - * 2D, @ref Magnum::Matrix4 in 3D. Used only if - * @ref Flag::InstancedTransformation is set. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - */ - typedef typename Generic::TransformationMatrix TransformationMatrix; - - /** - * @brief (Instanced) texture offset - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Vector2. Used - * only if @ref Flag::InstancedTextureOffset is set. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - */ - typedef typename Generic::TextureOffset TextureOffset; - - enum: UnsignedInt { - /** - * Color shader output. Present always, expects three- or - * four-component floating-point or normalized buffer attachment. - * @m_since{2019,10} - */ - ColorOutput = Generic::ColorOutput, - - #ifndef MAGNUM_TARGET_GLES2 - /** - * Object ID shader output. @ref shaders-generic "Generic output", - * present only if @ref Flag::ObjectId is set. Expects a - * single-component unsigned integral attachment. Writes the value - * set in @ref setObjectId() there, see - * @ref Shaders-Phong-object-id for more information. - * @requires_gl30 Extension @gl_extension{EXT,texture_integer} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL - * 1.0. - * @m_since{2019,10} - */ - ObjectIdOutput = Generic::ObjectIdOutput - #endif - }; - - #ifdef DOXYGEN_GENERATING_OUTPUT - /** - * @brief Flag - * - * @see @ref Flags, @ref flags() - */ - enum class Flag: UnsignedByte { - /** - * Multiply color with a texture. - * @see @ref setColor(), @ref bindTexture() - */ - Textured = 1 << 0, - - /** - * Enable alpha masking. If the combined fragment color has an - * alpha less than the value specified with @ref setAlphaMask(), - * given fragment is discarded. - * - * This uses the @glsl discard @ce operation which is known to have - * considerable performance impact on some platforms. While useful - * for cheap alpha masking that doesn't require depth sorting, - * with proper depth sorting and blending you'll usually get much - * better performance and output quality. - */ - AlphaMask = 1 << 1, - - /** - * Multiply diffuse color with a vertex color. Requires either - * the @ref Color3 or @ref Color4 attribute to be present. - * @m_since{2019,10} - */ - VertexColor = 1 << 2, - - /** - * Enable texture coordinate transformation. If this flag is set, - * the shader expects that @ref Flag::Textured is enabled as well. - * @see @ref setTextureMatrix() - * @m_since{2020,06} - */ - TextureTransformation = 1 << 3, - - #ifndef MAGNUM_TARGET_GLES2 - /** - * Enable object ID output. See @ref Shaders-Flat-object-id for - * more information. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL - * 1.0. - * @m_since{2019,10} - */ - ObjectId = 1 << 4, - - /** - * Instanced object ID. Retrieves a per-instance / per-vertex - * object ID from the @ref ObjectId attribute, outputting a sum of - * the per-vertex ID and ID coming from @ref setObjectId(). - * Implicitly enables @ref Flag::ObjectId. See - * @ref Shaders-Flat-object-id for more information. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL - * 1.0. - * @m_since{2020,06} - */ - InstancedObjectId = (1 << 5)|ObjectId, - #endif - - /** - * Instanced transformation. Retrieves a per-instance - * transformation matrix from the @ref TransformationMatrix - * attribute and uses it together with the matrix coming from - * @ref setTransformationProjectionMatrix() (first the - * per-instance, then the uniform matrix). See - * @ref Shaders-Flat-instancing for more information. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - * @m_since{2020,06} - */ - InstancedTransformation = 1 << 6, - - /** - * Instanced texture offset. Retrieves a per-instance offset vector - * from the @ref TextureOffset attribute and uses it together with - * the matrix coming from @ref setTextureMatrix() (first the - * per-instance vector, then the uniform matrix). Instanced texture - * scaling and rotation is not supported at the moment, you can - * specify that only via the uniform @ref setTextureMatrix(). - * Implicitly enables @ref Flag::TextureTransformation. See - * @ref Shaders-Flat-instancing for more information. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - * @m_since{2020,06} - */ - InstancedTextureOffset = (1 << 7)|TextureTransformation - }; - - /** - * @brief Flags - * - * @see @ref flags() - */ - typedef Containers::EnumSet Flags; - #else - /* Done this way to be prepared for possible future diversion of 2D - and 3D flags (e.g. introducing 3D-specific features) */ - typedef Implementation::FlatFlag Flag; - typedef Implementation::FlatFlags Flags; - #endif - - /** - * @brief Constructor - * @param flags Flags - */ - explicit Flat(Flags flags = {}); - - /** - * @brief Construct without creating the underlying OpenGL object - * - * The constructed instance is equivalent to a moved-from state. Useful - * in cases where you will overwrite the instance later anyway. Move - * another object over it to make it useful. - * - * This function can be safely used for constructing (and later - * destructing) objects even without any OpenGL context being active. - * However note that this is a low-level and a potentially dangerous - * API, see the documentation of @ref NoCreate for alternatives. - */ - explicit Flat(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - - /** @brief Copying is not allowed */ - Flat(const Flat&) = delete; - - /** @brief Move constructor */ - Flat(Flat&&) noexcept = default; - - /** @brief Copying is not allowed */ - Flat& operator=(const Flat&) = delete; - - /** @brief Move assignment */ - Flat& operator=(Flat&&) noexcept = default; - - /** @brief Flags */ - Flags flags() const { return _flags; } - - /** - * @brief Set transformation and projection matrix - * @return Reference to self (for method chaining) - * - * Initial value is an identity matrix. - */ - Flat& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); - - /** - * @brief Set texture coordinate transformation matrix - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * Expects that the shader was created with - * @ref Flag::TextureTransformation enabled. Initial value is an - * identity matrix. - */ - Flat& setTextureMatrix(const Matrix3& matrix); - - /** - * @brief Set color - * @return Reference to self (for method chaining) - * - * If @ref Flag::Textured is set, initial value is - * @cpp 0xffffffff_rgbaf @ce and the color will be multiplied with the - * texture. - * @see @ref bindTexture() - */ - Flat& setColor(const Magnum::Color4& color); - - /** - * @brief Bind a color texture - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::Textured - * enabled. - * @see @ref setColor(), @ref Flag::TextureTransformation, - * @ref setTextureMatrix() - */ - Flat& bindTexture(GL::Texture2D& texture); +#include "Magnum/configure.h" - /** - * @brief Set alpha mask value - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::AlphaMask - * enabled. Fragments with alpha values smaller than the mask value - * will be discarded. Initial value is @cpp 0.5f @ce. See the flag - * documentation for further information. - * - * This corresponds to @m_class{m-doc-external} [glAlphaFunc()](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAlphaFunc.xml) - * in classic OpenGL. - * @m_keywords{glAlphaFunc()} - */ - Flat& setAlphaMask(Float mask); +#ifdef MAGNUM_BUILD_DEPRECATED +#include - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief Set object ID - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::ObjectId - * enabled. Value set here is written to the @ref ObjectIdOutput, see - * @ref Shaders-Flat-object-id for more information. Default is - * @cpp 0 @ce. If @ref Flag::InstancedObjectId is enabled as well, this - * value is combined with ID coming from the @ref ObjectId attribute. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. - */ - Flat& setObjectId(UnsignedInt id); - #endif +#include "Magnum/Shaders/FlatGL.h" - private: - /* Prevent accidentally calling irrelevant functions */ - #ifndef MAGNUM_TARGET_GLES - using GL::AbstractShaderProgram::drawTransformFeedback; - #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - using GL::AbstractShaderProgram::dispatchCompute; - #endif +CORRADE_DEPRECATED_FILE("use Magnum/Shaders/FlatGL.h, the FlatGL class and related typedefs instead") - Flags _flags; - Int _transformationProjectionMatrixUniform{0}, - _textureMatrixUniform{1}, - _colorUniform{2}, - _alphaMaskUniform{3}; - #ifndef MAGNUM_TARGET_GLES2 - Int _objectIdUniform{4}; - #endif -}; +namespace Magnum { namespace Shaders { -/** @brief 2D flat shader */ -typedef Flat<2> Flat2D; +/** @brief @copybrief FlatGL + * @m_deprecated_since_latest Use @ref FlatGL instead. + */ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using Flat CORRADE_DEPRECATED_ALIAS("use FlatGL instead") = FlatGL; +#endif -/** @brief 3D flat shader */ -typedef Flat<3> Flat3D; +/** @brief @copybrief FlatGL2D + * @m_deprecated_since_latest Use @ref FlatGL2D instead. + */ +typedef CORRADE_DEPRECATED("use FlatGL2D instead") FlatGL2D Flat2D; -#ifdef DOXYGEN_GENERATING_OUTPUT -/** @debugoperatorclassenum{Flat,Flat::Flag} */ -template Debug& operator<<(Debug& debug, Flat::Flag value); +/** @brief @copybrief FlatGL3D + * @m_deprecated_since_latest Use @ref FlatGL3D instead. + */ +typedef CORRADE_DEPRECATED("use FlatGL3D instead") FlatGL3D Flat3D; -/** @debugoperatorclassenum{Flat,Flat::Flags} */ -template Debug& operator<<(Debug& debug, Flat::Flags value); +}} #else -namespace Implementation { - MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, FlatFlag value); - MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, FlatFlags value); - CORRADE_ENUMSET_OPERATORS(FlatFlags) -} +#error use Magnum/Shaders/FlatGL.h, the FlatGL class and related typedefs instead #endif -}} - #endif diff --git a/src/Magnum/Shaders/Flat.cpp b/src/Magnum/Shaders/FlatGL.cpp similarity index 78% rename from src/Magnum/Shaders/Flat.cpp rename to src/Magnum/Shaders/FlatGL.cpp index f55ca547f..3d9b1c79e 100644 --- a/src/Magnum/Shaders/Flat.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "Flat.h" +#include "FlatGL.h" #include #include @@ -45,16 +45,16 @@ namespace { enum: Int { TextureUnit = 0 }; } -template Flat::Flat(const Flags flags): _flags(flags) { +template FlatGL::FlatGL(const Flags flags): _flags(flags) { CORRADE_ASSERT(!(flags & Flag::TextureTransformation) || (flags & Flag::Textured), - "Shaders::Flat: texture transformation enabled but the shader is not textured", ); + "Shaders::FlatGL: texture transformation enabled but the shader is not textured", ); #ifdef MAGNUM_BUILD_STATIC /* Import resources on static build, if not already */ - if(!Utility::Resource::hasGroup("MagnumShaders")) + if(!Utility::Resource::hasGroup("MagnumShadersGL")) importShaderResources(); #endif - Utility::Resource rs("MagnumShaders"); + Utility::Resource rs("MagnumShadersGL"); #ifndef MAGNUM_TARGET_GLES const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); @@ -151,57 +151,57 @@ template Flat::Flat(const Flags flags): _fla #endif } -template Flat& Flat::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { +template FlatGL& FlatGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { setUniform(_transformationProjectionMatrixUniform, matrix); return *this; } -template Flat& Flat::setTextureMatrix(const Matrix3& matrix) { +template FlatGL& FlatGL::setTextureMatrix(const Matrix3& matrix) { CORRADE_ASSERT(_flags & Flag::TextureTransformation, - "Shaders::Flat::setTextureMatrix(): the shader was not created with texture transformation enabled", *this); + "Shaders::FlatGL::setTextureMatrix(): the shader was not created with texture transformation enabled", *this); setUniform(_textureMatrixUniform, matrix); return *this; } -template Flat& Flat::setColor(const Magnum::Color4& color) { +template FlatGL& FlatGL::setColor(const Magnum::Color4& color) { setUniform(_colorUniform, color); return *this; } -template Flat& Flat::bindTexture(GL::Texture2D& texture) { +template FlatGL& FlatGL::bindTexture(GL::Texture2D& texture) { CORRADE_ASSERT(_flags & Flag::Textured, - "Shaders::Flat::bindTexture(): the shader was not created with texturing enabled", *this); + "Shaders::FlatGL::bindTexture(): the shader was not created with texturing enabled", *this); texture.bind(TextureUnit); return *this; } -template Flat& Flat::setAlphaMask(Float mask) { +template FlatGL& FlatGL::setAlphaMask(Float mask) { CORRADE_ASSERT(_flags & Flag::AlphaMask, - "Shaders::Flat::setAlphaMask(): the shader was not created with alpha mask enabled", *this); + "Shaders::FlatGL::setAlphaMask(): the shader was not created with alpha mask enabled", *this); setUniform(_alphaMaskUniform, mask); return *this; } #ifndef MAGNUM_TARGET_GLES2 -template Flat& Flat::setObjectId(UnsignedInt id) { +template FlatGL& FlatGL::setObjectId(UnsignedInt id) { CORRADE_ASSERT(_flags & Flag::ObjectId, - "Shaders::Flat::setObjectId(): the shader was not created with object ID enabled", *this); + "Shaders::FlatGL::setObjectId(): the shader was not created with object ID enabled", *this); setUniform(_objectIdUniform, id); return *this; } #endif -template class Flat<2>; -template class Flat<3>; +template class FlatGL<2>; +template class FlatGL<3>; namespace Implementation { -Debug& operator<<(Debug& debug, const FlatFlag value) { - debug << "Shaders::Flat::Flag" << Debug::nospace; +Debug& operator<<(Debug& debug, const FlatGLFlag value) { + debug << "Shaders::FlatGL::Flag" << Debug::nospace; switch(value) { /* LCOV_EXCL_START */ - #define _c(v) case FlatFlag::v: return debug << "::" #v; + #define _c(v) case FlatGLFlag::v: return debug << "::" #v; _c(Textured) _c(AlphaMask) _c(VertexColor) @@ -219,18 +219,18 @@ Debug& operator<<(Debug& debug, const FlatFlag value) { return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } -Debug& operator<<(Debug& debug, const FlatFlags value) { - return Containers::enumSetDebugOutput(debug, value, "Shaders::Flat::Flags{}", { - FlatFlag::Textured, - FlatFlag::AlphaMask, - FlatFlag::VertexColor, - FlatFlag::InstancedTextureOffset, /* Superset of TextureTransformation */ - FlatFlag::TextureTransformation, +Debug& operator<<(Debug& debug, const FlatGLFlags value) { + return Containers::enumSetDebugOutput(debug, value, "Shaders::FlatGL::Flags{}", { + FlatGLFlag::Textured, + FlatGLFlag::AlphaMask, + FlatGLFlag::VertexColor, + FlatGLFlag::InstancedTextureOffset, /* Superset of TextureTransformation */ + FlatGLFlag::TextureTransformation, #ifndef MAGNUM_TARGET_GLES2 - FlatFlag::InstancedObjectId, /* Superset of ObjectId */ - FlatFlag::ObjectId, + FlatGLFlag::InstancedObjectId, /* Superset of ObjectId */ + FlatGLFlag::ObjectId, #endif - FlatFlag::InstancedTransformation}); + FlatGLFlag::InstancedTransformation}); } } diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h new file mode 100644 index 000000000..7256bf3cf --- /dev/null +++ b/src/Magnum/Shaders/FlatGL.h @@ -0,0 +1,539 @@ +#ifndef Magnum_Shaders_FlatGL_h +#define Magnum_Shaders_FlatGL_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Shaders::FlatGL, typedef @ref Magnum::Shaders::FlatGL2D, @ref Magnum::Shaders::FlatGL3D + * @m_since_latest + */ + +#include "Magnum/DimensionTraits.h" +#include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/Shaders/GenericGL.h" +#include "Magnum/Shaders/visibility.h" + +namespace Magnum { namespace Shaders { + +namespace Implementation { + enum class FlatGLFlag: UnsignedByte { + Textured = 1 << 0, + AlphaMask = 1 << 1, + VertexColor = 1 << 2, + TextureTransformation = 1 << 3, + #ifndef MAGNUM_TARGET_GLES2 + ObjectId = 1 << 4, + InstancedObjectId = (1 << 5)|ObjectId, + #endif + InstancedTransformation = 1 << 6, + InstancedTextureOffset = (1 << 7)|TextureTransformation + }; + typedef Containers::EnumSet FlatGLFlags; +} + +/** +@brief Flat OpenGL shader +@m_since_latest + +Draws the whole mesh with given color or texture. For a colored mesh you need +to provide the @ref Position attribute in your triangle mesh. By default, the +shader renders the mesh with a white color in an identity transformation. +Use @ref setTransformationProjectionMatrix(), @ref setColor() and others to +configure the shader. + +@image html shaders-flat.png width=256px + +@section Shaders-FlatGL-colored Colored rendering + +Common mesh setup: + +@snippet MagnumShaders-gl.cpp FlatGL-usage-colored1 + +Common rendering setup: + +@snippet MagnumShaders-gl.cpp FlatGL-usage-colored2 + +@section Shaders-FlatGL-textured Textured rendering + +If you want to use a texture, you need to provide also the +@ref TextureCoordinates attribute. Pass @ref Flag::Textured to the constructor +and then at render time don't forget to bind also the texture via +@ref bindTexture(). The texture is multipled by the color, which is by default +set to @cpp 0xffffffff_rgbaf @ce. Common mesh setup: + +@snippet MagnumShaders-gl.cpp FlatGL-usage-textured1 + +Common rendering setup: + +@snippet MagnumShaders-gl.cpp FlatGL-usage-textured2 + +For coloring the texture based on intensity you can use the @ref VectorGL +shader. The 3D version of this shader is equivalent to @ref PhongGL with zero +lights, however this implementation is much simpler and thus likely also +faster. See @ref Shaders-PhongGL-lights-zero "its documentation" for more +information. Conversely, enabling @ref Flag::VertexColor and using a default +color with no texturing makes this shader equivalent to @ref VertexColorGL. + +@section Shaders-FlatGL-alpha Alpha blending and masking + +Alpha / transparency is supported by the shader implicitly, but to have it +working on the framebuffer, you need to enable +@ref GL::Renderer::Feature::Blending and set up the blending function. See +@ref GL::Renderer::setBlendFunction() for details. + +An alternative is to enable @ref Flag::AlphaMask and tune @ref setAlphaMask() +for simple binary alpha-masked drawing that doesn't require depth sorting or +blending enabled. Note that this feature is implemented using the GLSL +@glsl discard @ce operation which is known to have considerable performance +impact on some platforms. With proper depth sorting and blending you'll usually +get much better performance and output quality. + +@section Shaders-FlatGL-object-id Object ID output + +The shader supports writing object ID to the framebuffer for object picking or +other annotation purposes. Enable it using @ref Flag::ObjectId and set up an +integer buffer attached to the @ref ObjectIdOutput attachment. Note that for +portability you should use @ref GL::Framebuffer::clearColor() instead of +@ref GL::Framebuffer::clear() as the former usually emits GL errors when called +on framebuffers with integer attachments. + +@snippet MagnumShaders-gl.cpp FlatGL-usage-object-id + +If you have a batch of meshes with different object IDs, enable +@ref Flag::InstancedObjectId and supply per-vertex IDs to the @ref ObjectId +attribute. The output will contain a sum of the per-vertex ID and ID coming +from @ref setObjectId(). + +@requires_gles30 Object ID output requires integer buffer attachments, which + are not available in OpenGL ES 2.0 or WebGL 1.0. + +@section Shaders-FlatGL-instancing Instanced rendering + +Enabling @ref Flag::InstancedTransformation will turn the shader into an +instanced one. It'll take per-instance transformation from the +@ref TransformationMatrix attribute, applying it before the matrix set by +@ref setTransformationProjectionMatrix(). Besides that, @ref Flag::VertexColor +(and the @ref Color3 / @ref Color4) attributes can work as both per-vertex and +per-instance, and for texturing it's possible to have per-instance texture +offset taken from @ref TextureOffset when @ref Flag::InstancedTextureOffset is +enabled (similarly to transformation, applied before @ref setTextureMatrix()). +The snippet below shows adding a buffer with per-instance transformation and +color to a mesh: + +@snippet MagnumShaders-gl.cpp FlatGL-usage-instancing + +@requires_gl33 Extension @gl_extension{ARB,instanced_arrays} +@requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + @gl_extension{EXT,instanced_arrays} or @gl_extension{NV,instanced_arrays} + in OpenGL ES 2.0. +@requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} in WebGL + 1.0. + +@see @ref shaders, @ref FlatGL2D, @ref FlatGL3D +*/ +template class MAGNUM_SHADERS_EXPORT FlatGL: public GL::AbstractShaderProgram { + public: + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector2 "Vector2" in 2D, @ref Magnum::Vector3 "Vector3" + * in 3D. + */ + typedef typename GenericGL::Position Position; + + /** + * @brief 2D texture coordinates + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector2 "Vector2". Used only if @ref Flag::Textured is + * set. + */ + typedef typename GenericGL::TextureCoordinates TextureCoordinates; + + /** + * @brief Three-component vertex color + * @m_since{2019,10} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color3. Use + * either this or the @ref Color4 attribute. Used only if + * @ref Flag::VertexColor is set. + */ + typedef typename GenericGL::Color3 Color3; + + /** + * @brief Four-component vertex color + * @m_since{2019,10} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color4. Use + * either this or the @ref Color3 attribute. Used only if + * @ref Flag::VertexColor is set. + */ + typedef typename GenericGL::Color4 Color4; + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief (Instanced) object ID + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. + * Used only if @ref Flag::InstancedObjectId is set. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. + */ + typedef typename GenericGL::ObjectId ObjectId; + #endif + + /** + * @brief (Instanced) transformation matrix + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Matrix3 in + * 2D, @ref Magnum::Matrix4 in 3D. Used only if + * @ref Flag::InstancedTransformation is set. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + */ + typedef typename GenericGL::TransformationMatrix TransformationMatrix; + + /** + * @brief (Instanced) texture offset + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Vector2. Used + * only if @ref Flag::InstancedTextureOffset is set. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + */ + typedef typename GenericGL::TextureOffset TextureOffset; + + enum: UnsignedInt { + /** + * Color shader output. Present always, expects three- or + * four-component floating-point or normalized buffer attachment. + * @m_since{2019,10} + */ + ColorOutput = GenericGL::ColorOutput, + + #ifndef MAGNUM_TARGET_GLES2 + /** + * Object ID shader output. @ref shaders-generic "Generic output", + * present only if @ref Flag::ObjectId is set. Expects a + * single-component unsigned integral attachment. Writes the value + * set in @ref setObjectId() there, see + * @ref Shaders-FlatGL-object-id for more information. + * @requires_gl30 Extension @gl_extension{EXT,texture_integer} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL + * 1.0. + * @m_since{2019,10} + */ + ObjectIdOutput = GenericGL::ObjectIdOutput + #endif + }; + + #ifdef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Flag + * + * @see @ref Flags, @ref flags() + */ + enum class Flag: UnsignedByte { + /** + * Multiply color with a texture. + * @see @ref setColor(), @ref bindTexture() + */ + Textured = 1 << 0, + + /** + * Enable alpha masking. If the combined fragment color has an + * alpha less than the value specified with @ref setAlphaMask(), + * given fragment is discarded. + * + * This uses the @glsl discard @ce operation which is known to have + * considerable performance impact on some platforms. While useful + * for cheap alpha masking that doesn't require depth sorting, + * with proper depth sorting and blending you'll usually get much + * better performance and output quality. + */ + AlphaMask = 1 << 1, + + /** + * Multiply diffuse color with a vertex color. Requires either + * the @ref Color3 or @ref Color4 attribute to be present. + * @m_since{2019,10} + */ + VertexColor = 1 << 2, + + /** + * Enable texture coordinate transformation. If this flag is set, + * the shader expects that @ref Flag::Textured is enabled as well. + * @see @ref setTextureMatrix() + * @m_since{2020,06} + */ + TextureTransformation = 1 << 3, + + #ifndef MAGNUM_TARGET_GLES2 + /** + * Enable object ID output. See @ref Shaders-FlatGL-object-id for + * more information. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL + * 1.0. + * @m_since{2019,10} + */ + ObjectId = 1 << 4, + + /** + * Instanced object ID. Retrieves a per-instance / per-vertex + * object ID from the @ref ObjectId attribute, outputting a sum of + * the per-vertex ID and ID coming from @ref setObjectId(). + * Implicitly enables @ref Flag::ObjectId. See + * @ref Shaders-FlatGL-object-id for more information. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL + * 1.0. + * @m_since{2020,06} + */ + InstancedObjectId = (1 << 5)|ObjectId, + #endif + + /** + * Instanced transformation. Retrieves a per-instance + * transformation matrix from the @ref TransformationMatrix + * attribute and uses it together with the matrix coming from + * @ref setTransformationProjectionMatrix() (first the + * per-instance, then the uniform matrix). See + * @ref Shaders-FlatGL-instancing for more information. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + * @m_since{2020,06} + */ + InstancedTransformation = 1 << 6, + + /** + * Instanced texture offset. Retrieves a per-instance offset vector + * from the @ref TextureOffset attribute and uses it together with + * the matrix coming from @ref setTextureMatrix() (first the + * per-instance vector, then the uniform matrix). Instanced texture + * scaling and rotation is not supported at the moment, you can + * specify that only via the uniform @ref setTextureMatrix(). + * Implicitly enables @ref Flag::TextureTransformation. See + * @ref Shaders-FlatGL-instancing for more information. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + * @m_since{2020,06} + */ + InstancedTextureOffset = (1 << 7)|TextureTransformation + }; + + /** + * @brief Flags + * + * @see @ref flags() + */ + typedef Containers::EnumSet Flags; + #else + /* Done this way to be prepared for possible future diversion of 2D + and 3D flags (e.g. introducing 3D-specific features) */ + typedef Implementation::FlatGLFlag Flag; + typedef Implementation::FlatGLFlags Flags; + #endif + + /** + * @brief Constructor + * @param flags Flags + */ + explicit FlatGL(Flags flags = {}); + + /** + * @brief Construct without creating the underlying OpenGL object + * + * The constructed instance is equivalent to a moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit FlatGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} + + /** @brief Copying is not allowed */ + FlatGL(const FlatGL&) = delete; + + /** @brief Move constructor */ + FlatGL(FlatGL&&) noexcept = default; + + /** @brief Copying is not allowed */ + FlatGL& operator=(const FlatGL&) = delete; + + /** @brief Move assignment */ + FlatGL& operator=(FlatGL&&) noexcept = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set transformation and projection matrix + * @return Reference to self (for method chaining) + * + * Initial value is an identity matrix. + */ + FlatGL& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); + + /** + * @brief Set texture coordinate transformation matrix + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * Expects that the shader was created with + * @ref Flag::TextureTransformation enabled. Initial value is an + * identity matrix. + */ + FlatGL& setTextureMatrix(const Matrix3& matrix); + + /** + * @brief Set color + * @return Reference to self (for method chaining) + * + * If @ref Flag::Textured is set, initial value is + * @cpp 0xffffffff_rgbaf @ce and the color will be multiplied with the + * texture. + * @see @ref bindTexture() + */ + FlatGL& setColor(const Magnum::Color4& color); + + /** + * @brief Bind a color texture + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::Textured + * enabled. + * @see @ref setColor(), @ref Flag::TextureTransformation, + * @ref setTextureMatrix() + */ + FlatGL& bindTexture(GL::Texture2D& texture); + + /** + * @brief Set alpha mask value + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::AlphaMask + * enabled. Fragments with alpha values smaller than the mask value + * will be discarded. Initial value is @cpp 0.5f @ce. See the flag + * documentation for further information. + * + * This corresponds to @m_class{m-doc-external} [glAlphaFunc()](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAlphaFunc.xml) + * in classic OpenGL. + * @m_keywords{glAlphaFunc()} + */ + FlatGL& setAlphaMask(Float mask); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Set object ID + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::ObjectId + * enabled. Value set here is written to the @ref ObjectIdOutput, see + * @ref Shaders-FlatGL-object-id for more information. Default is + * @cpp 0 @ce. If @ref Flag::InstancedObjectId is enabled as well, this + * value is combined with ID coming from the @ref ObjectId attribute. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. + */ + FlatGL& setObjectId(UnsignedInt id); + #endif + + private: + /* Prevent accidentally calling irrelevant functions */ + #ifndef MAGNUM_TARGET_GLES + using GL::AbstractShaderProgram::drawTransformFeedback; + #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + using GL::AbstractShaderProgram::dispatchCompute; + #endif + + Flags _flags; + Int _transformationProjectionMatrixUniform{0}, + _textureMatrixUniform{1}, + _colorUniform{2}, + _alphaMaskUniform{3}; + #ifndef MAGNUM_TARGET_GLES2 + Int _objectIdUniform{4}; + #endif +}; + +/** +@brief 2D flat OpenGL shader +@m_since_latest +*/ +typedef FlatGL<2> FlatGL2D; + +/** +@brief 3D flat OpenGL shader +@m_since_latest +*/ +typedef FlatGL<3> FlatGL3D; + +#ifdef DOXYGEN_GENERATING_OUTPUT +/** @debugoperatorclassenum{FlatGL,FlatGL::Flag} */ +template Debug& operator<<(Debug& debug, FlatGL::Flag value); + +/** @debugoperatorclassenum{FlatGL,FlatGL::Flags} */ +template Debug& operator<<(Debug& debug, FlatGL::Flags value); +#else +namespace Implementation { + MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, FlatGLFlag value); + MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, FlatGLFlags value); + CORRADE_ENUMSET_OPERATORS(FlatGLFlags) +} +#endif + +}} + +#endif diff --git a/src/Magnum/Shaders/Generic.h b/src/Magnum/Shaders/Generic.h index 149e6f5b1..e588298ec 100644 --- a/src/Magnum/Shaders/Generic.h +++ b/src/Magnum/Shaders/Generic.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Shaders_GenericShader_h -#define Magnum_Shaders_GenericShader_h +#ifndef Magnum_Shaders_Generic_h +#define Magnum_Shaders_Generic_h /* This file is part of Magnum. @@ -25,462 +25,32 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file - * @brief Struct @ref Magnum::Shaders::Generic, typedef @ref Magnum::Shaders::Generic2D, @ref Magnum::Shaders::Generic3D + * @brief Typedef @ref Magnum::Shaders::Generic, alias @ref Magnum::Shaders::Generic2D, @ref Magnum::Shaders::Generic3D + * @m_deprecated_since_latest Use @ref Magnum/Shaders/GenericGL.h, the + * @ref Magnum::Shaders::GenericGL "GenericGL" class and + * related typedefs instead. */ - -#include "Magnum/GL/Attribute.h" - -namespace Magnum { namespace Shaders { - -/** -@brief Generic shader definition - -Definitions common for majority of shaders in the @ref Shaders namespace, -allowing mesh or a framebuffer configured for a generic shader to be used with -any of them. See @ref shaders-generic for more information. - -@section Shaders-Generic-allocation Attribute allocation - -The attribute locations are allocated like shown below, with various tradeoffs -as GPUs commonly support only 16 attribtes at most, while the mandated minimum -on OpenGL ES2 and WebGL 1 being only 8. Some locations are only reserved for -future use, with no attribute definition implemented yet. - -@m_class{m-row m-container-inflate} - -@parblock - -@m_class{m-fullwidth} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
\#AttributeAlternativeAlternative 2
0 -@ref Position -
1 -@ref TextureCoordinates - -* *Reserved* --- third component for a layer -
2 -@ref Color3 / @ref Color4 (per-vertex or instanced) -
3 -@ref Tangent / @ref Tangent4 - -@ref Tangent - -* *Reserved* --- TBN as a @ref Magnum::Quaternion "Quaternion" -
4 -@ref ObjectId (instanced) - -* *Reserved* --- additional components could \n -represent material ID and other indices, which \n -could then be used to fetch additional \n -per-instance properties that wouldn't fit into \n -vertex attributes. - -@ref Bitangent - -Provided only as a convenience for models that \n -don't encode bitangent orientation in the last \n -component of @ref Tangent4. If a model needs \n -both bitangents and object ID for instancing, \n -@ref Tangent4 has to be used. -
5 -@ref Normal -
6 -* *Reserved* --- vertex weights -
7 -* *Reserved* --- bone indices -
8 -@ref TransformationMatrix (instanced) - -* *Reserved* --- instanced @ref Magnum::DualQuaternion "DualQuaternion" \n transformation for positions and normals -
9
10 -* *Reserved* --- 2nd vertex weights -
11 -* *Reserved* --- 2nd bone indices -
12 -@ref NormalMatrix (instanced) - -* *Reserved* --- instanced scale for positions -
13 -* *Reserved* --- instanced texture \n -rotation and scale - -* *Reserved* --- 2nd vertex colors -
14 -* *Reserved* --- 3rd texture coords -
15 -@ref TextureOffset (instanced) - -* *Reserved* --- third component for a layer - -* *Reserved* --- a single component \n -representing instanced texture layer \n -index, UVs being the same always - -* *Reserved* --- 2nd texture coords -
- -@endparblock - -The three alternative allocations can be mixed freely as long as the locations -don't conflict --- so it's possible to have for example a mesh with two sets of -texture coordinates, weights and colors, as each of those occupies a different -attribute range; but instancing then has to be done using smaller types as full -matrices would occupy the locations used by the secondary sets. Additional -guarantees of the above: - -- @ref Tangent, @ref Bitangent and @ref Normal is in consecutive locations to - allow those being passed as a single TBN @ref Magnum::Matrix3x3 "Matrix3x3" - attribute as well. -- @ref Normal and TBN represented as a quaternion use different locations in - order to allow a mesh to contain both -- Similarly, texture rotation/scale and offset is in consecutive locations to - allow passing a single @ref Matrix3 attribute there. -- Tnstanced texture transformation is available if and only if there's - exactly one set of texture coordinates (as the additional sets would need - additional transformations as well). - -@section Shaders-Generic-custom Generic attributes and custom shaders - -Note that while custom shaders don't *have to* follow the above, it's -recommended to so. If the custom shader diverges from predefined locations of -common attributes, meshes configured for the builtin shaders (for example with -@ref MeshTools::compile()) won't work with it and the mesh attribute -configuration has to be done manually. It also becomes impossible to render a -mesh configured for a custom shader with for example @ref MeshVisualizer. - -If you're using @ref GL::AbstractShaderProgram::bindAttributeLocation(), it's -rather easy, as you can simply use the @ref GL::Attribute::Location of given -attribute: - -@snippet MagnumShaders.cpp Generic-custom-bind - -For attribute location defined directly in shader code (which is the -recommended way unless you need compatibility with WebGL 1.0 and OpenGL ES -2.0), the attribute locations can be propagated using a preprocessor define. -For example: - -@snippet MagnumShaders.cpp Generic-custom-preprocessor - -Then, the attribute definition in a shader will look like this: - -@code{.glsl} -layout(location = POSITION_ATTRIBUTE_LOCATION) in vec3 position; -layout(location = NORMAL_ATTRIBUTE_LOCATION) in vec3 normal; -@endcode - -@see @ref shaders, @ref Generic2D, @ref Generic3D -*/ -#ifndef DOXYGEN_GENERATING_OUTPUT -template struct Generic; -#else -template struct Generic { - /* Keep consistent with generic.glsl and the real definitions below */ - - enum: UnsignedInt { - /** - * Color shader output. Present always, expects three- or - * four-component floating-point or normalized buffer attachment. - */ - ColorOutput = 0, - - #ifndef MAGNUM_TARGET_GLES2 - /** - * Object ID shader output. Expects a single-component unsigned - * integral attachment. - * @requires_gl30 Extension @gl_extension{EXT,texture_integer} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. - */ - ObjectIdOutput = 1 - #endif - }; - - /** - * @brief Vertex position - * - * @ref Magnum::Vector2 "Vector2" in 2D and @ref Magnum::Vector3 "Vector3" - * in 3D. Corresponds to @ref Trade::MeshAttribute::Position. - */ - typedef GL::Attribute<0, T> Position; - - /** - * @brief 2D texture coordinates - * - * @ref Magnum::Vector2 "Vector2". Corresponds to - * @ref Trade::MeshAttribute::TextureCoordinates. - */ - typedef GL::Attribute<1, Vector2> TextureCoordinates; - - /** - * @brief Three-component vertex color - * - * @ref Magnum::Color3. Use either this or the @ref Color4 attribute. - * Corresponds to @ref Trade::MeshAttribute::Color. - */ - typedef GL::Attribute<2, Magnum::Color3> Color3; - - /** - * @brief Four-component vertex color - * - * @ref Magnum::Color4. Use either this or the @ref Color3 attribute. - * Corresponds to @ref Trade::MeshAttribute::Color. - */ - typedef GL::Attribute<2, Magnum::Color4> Color4; - - /** - * @brief Vertex tangent - * @m_since{2019,10} - * - * @ref Magnum::Vector3 "Vector3", defined only in 3D. Use either this or - * the @ref Tangent4 attribute. Corresponds to - * @ref Trade::MeshAttribute::Tangent. - */ - typedef GL::Attribute<3, Vector3> Tangent; - - /** - * @brief Vertex tangent with a bitangent sign - * @m_since{2020,06} - * - * @ref Magnum::Vector4 "Vector4", defined only in 3D. The last component - * is a sign value (@cpp -1.0f @ce or @cpp +1.0f @ce) defining handedness - * of the tangent basis. Reconstructing the @ref Bitangent attribute can be - * then done like this: - * - * @snippet MagnumTrade.cpp MeshAttribute-bitangent-from-tangent - * - * Use either this or the @ref Tangent attribute. Corresponds to - * @ref Trade::MeshAttribute::Tangent. - */ - typedef GL::Attribute<3, Vector4> Tangent4; - - /** - * @brief Vertex bitangent - * @m_since{2020,06} - * - * @ref Magnum::Vector3 "Vector3", defined only in 3D. For better storage - * efficiency, the bitangent can be also reconstructed from the normal and - * tangent, see @ref Tangent4 for more information. Corresponds to - * @ref Trade::MeshAttribute::Bitangent. - * - * This attribute conflicts with @ref ObjectId, if you want to use both - * instanced object ID and bitangents, you need to reconstruct them from - * @ref Tangent4 instead. - */ - typedef GL::Attribute<4, Vector3> Bitangent; - - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief (Instanced) object ID - * @m_since{2020,06} - * - * @ref Magnum::UnsignedInt "UnsignedInt". Corresponds to - * @ref Trade::MeshAttribute::ObjectId. - * - * This attribute conflicts with @ref Bitangent, if you want to use both - * instanced object ID and bitangents, you need to reconstruct them from - * @ref Tangent4 instead. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in shaders, - * which is not available in OpenGL ES 2.0 or WebGL 1.0. - */ - typedef GL::Attribute<4, UnsignedInt> ObjectId; - #endif - - /* Index 4 also used by MeshVisualizer::VertexIndex (reusing ObjectId). Not - making it generic yet, as its use case is limited to a single shader, - and even there it's just a fallback for platforms w/o gl_VertexID. */ - - /** - * @brief Vertex normal - * - * @ref Magnum::Vector3 "Vector3", defined only in 3D. Corresponds to - * @ref Trade::MeshAttribute::Normal. - */ - typedef GL::Attribute<5, Vector3> Normal; - - /* 6, 7 reserved for vertex weights / bone IDs */ - - /** - * @brief (Instanced) transformation matrix - * @m_since{2020,06} - * - * @ref Magnum::Matrix3 "Matrix3" in 2D and @ref Magnum::Matrix4 "Matrix4" - * in 3D. Currently doesn't have a corresponding @ref Trade::MeshAttribute. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - */ - typedef GL::Attribute<8, T> TransformationMatrix; - - /* 9, 10, 11 occupied by TransformationMatrix */ - - /** - * @brief (Instanced) normal matrix - * @m_since{2020,06} - * - * @ref Magnum::Matrix3 "Matrix3x3", defined only in 3D. Currently doesn't - * have a corresponding @ref Trade::MeshAttribute. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - */ - typedef GL::Attribute<12, Matrix3x3> NormalMatrix; - - /* 13, 14 occupied by NormalMatrix */ - - /** - * @brief (Instanced) texture offset - * @m_since{2020,06} - * - * @ref Magnum::Vector2 "Vector2". Currently doesn't have a corresponding - * @ref Trade::MeshAttribute. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - */ - typedef GL::Attribute<15, Vector2> TextureOffset; -}; #endif -/** @brief Generic 2D shader definition */ -typedef Generic<2> Generic2D; +#include "Magnum/configure.h" -/** @brief Generic 3D shader definition */ -typedef Generic<3> Generic3D; +#ifdef MAGNUM_BUILD_DEPRECATED +#include -#ifndef DOXYGEN_GENERATING_OUTPUT -struct BaseGeneric { - enum: UnsignedInt { - ColorOutput = 0, - #ifndef MAGNUM_TARGET_GLES2 - ObjectIdOutput = 1 - #endif - }; +#include "Magnum/Shaders/GenericGL.h" - typedef GL::Attribute<1, Vector2> TextureCoordinates; - typedef GL::Attribute<2, Magnum::Color3> Color3; - typedef GL::Attribute<2, Magnum::Color4> Color4; - #ifndef MAGNUM_TARGET_GLES2 - typedef GL::Attribute<4, UnsignedInt> ObjectId; - #endif +CORRADE_DEPRECATED_FILE("use Magnum/Shaders/GenericGL.h, the GenericGL class and related typedefs instead") - typedef GL::Attribute<15, Vector2> TextureOffset; -}; - -template<> struct Generic<2>: BaseGeneric { - typedef GL::Attribute<0, Vector2> Position; - /* 1, 2 used by TextureCoordinates and Color */ - - typedef GL::Attribute<8, Matrix3> TransformationMatrix; - /* 9, 10 occupied by TransformationMatrix */ - /* 15 used by TextureOffset */ -}; - -template<> struct Generic<3>: BaseGeneric { - typedef GL::Attribute<0, Vector3> Position; - /* 1, 2 used by TextureCoordinates and Color */ - typedef GL::Attribute<3, Vector3> Tangent; - typedef GL::Attribute<3, Vector4> Tangent4; - typedef GL::Attribute<4, Vector3> Bitangent; /* also ObjectId */ - typedef GL::Attribute<5, Vector3> Normal; - /* 6, 7 reserved for vertex weights / bone IDs */ - - typedef GL::Attribute<8, Matrix4> TransformationMatrix; - /* 9, 10, 11 occupied by TransformationMatrix */ - typedef GL::Attribute<12, Matrix3x3> NormalMatrix; - /* 13, 14 occupied by NormalMatrix */ - /* 15 used by TextureOffset */ -}; +/* Deprecated aliases not present here but in GenericGL.h instead, as a lot of + existing code relies on these being transitively included from Phong.h etc., + and there are no forward declarations in Shaders.h as the type is never used + like that. While we *could* include Generic.h from Phong.h, we'd have to + also temporarily disable the CORRADE_DEPRECATED_FILE() macro there and it's + more pain than it's worth. */ +#else +#error use Magnum/Shaders/GenericGL.h, the GenericGL class and related typedefs instead #endif -}} - #endif diff --git a/src/Magnum/Shaders/GenericGL.h b/src/Magnum/Shaders/GenericGL.h new file mode 100644 index 000000000..d40318ae3 --- /dev/null +++ b/src/Magnum/Shaders/GenericGL.h @@ -0,0 +1,521 @@ +#ifndef Magnum_Shaders_GenericGL_h +#define Magnum_Shaders_GenericGL_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 Struct @ref Magnum::Shaders::GenericGL, typedef @ref Magnum::Shaders::GenericGL2D, @ref Magnum::Shaders::GenericGL3D + * @m_since_latest + */ + +#include "Magnum/GL/Attribute.h" +#include "Magnum/Shaders/Shaders.h" + +namespace Magnum { namespace Shaders { + +/** +@brief Generic OpenGL shader definition +@m_since_latest + +Definitions common for majority of OpenGL shaders in the @ref Shaders +namespace, allowing mesh or a framebuffer configured for a generic shader to be +used with any of them. See @ref shaders-generic for more information. + +@section Shaders-GenericGL-allocation Attribute allocation + +The attribute locations are allocated like shown below, with various tradeoffs +as GPUs commonly support only 16 attribtes at most, while the mandated minimum +on OpenGL ES2 and WebGL 1 being only 8. Some locations are only reserved for +future use, with no attribute definition implemented yet. + +@m_class{m-row m-container-inflate} + +@parblock + +@m_class{m-fullwidth} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\#AttributeAlternativeAlternative 2
0 +@ref Position +
1 +@ref TextureCoordinates + +* *Reserved* --- third component for a layer +
2 +@ref Color3 / @ref Color4 (per-vertex or instanced) +
3 +@ref Tangent / @ref Tangent4 + +@ref Tangent + +* *Reserved* --- TBN as a @ref Magnum::Quaternion "Quaternion" +
4 +@ref ObjectId (instanced) + +* *Reserved* --- additional components could \n +represent material ID and other indices, which \n +could then be used to fetch additional \n +per-instance properties that wouldn't fit into \n +vertex attributes. + +@ref Bitangent + +Provided only as a convenience for models that \n +don't encode bitangent orientation in the last \n +component of @ref Tangent4. If a model needs \n +both bitangents and object ID for instancing, \n +@ref Tangent4 has to be used. +
5 +@ref Normal +
6 +* *Reserved* --- vertex weights +
7 +* *Reserved* --- bone indices +
8 +@ref TransformationMatrix (instanced) + +* *Reserved* --- instanced @ref Magnum::DualQuaternion "DualQuaternion" \n transformation for positions and normals +
9
10 +* *Reserved* --- 2nd vertex weights +
11 +* *Reserved* --- 2nd bone indices +
12 +@ref NormalMatrix (instanced) + +* *Reserved* --- instanced scale for positions +
13 +* *Reserved* --- instanced texture \n +rotation and scale + +* *Reserved* --- 2nd vertex colors +
14 +* *Reserved* --- 3rd texture coords +
15 +@ref TextureOffset (instanced) + +* *Reserved* --- third component for a layer + +* *Reserved* --- a single component \n +representing instanced texture layer \n +index, UVs being the same always + +* *Reserved* --- 2nd texture coords +
+ +@endparblock + +The three alternative allocations can be mixed freely as long as the locations +don't conflict --- so it's possible to have for example a mesh with two sets of +texture coordinates, weights and colors, as each of those occupies a different +attribute range; but instancing then has to be done using smaller types as full +matrices would occupy the locations used by the secondary sets. Additional +guarantees of the above: + +- @ref Tangent, @ref Bitangent and @ref Normal is in consecutive locations to + allow those being passed as a single TBN @ref Magnum::Matrix3x3 "Matrix3x3" + attribute as well. +- @ref Normal and TBN represented as a quaternion use different locations in + order to allow a mesh to contain both +- Similarly, texture rotation/scale and offset is in consecutive locations to + allow passing a single @ref Matrix3 attribute there. +- Tnstanced texture transformation is available if and only if there's + exactly one set of texture coordinates (as the additional sets would need + additional transformations as well). + +@section Shaders-GenericGL-custom Generic attributes and custom shaders + +Note that while custom shaders don't *have to* follow the above, it's +recommended to so. If the custom shader diverges from predefined locations of +common attributes, meshes configured for the builtin shaders (for example with +@ref MeshTools::compile()) won't work with it and the mesh attribute +configuration has to be done manually. It also becomes impossible to render a +mesh configured for a custom shader with for example @ref MeshVisualizer. + +If you're using @ref GL::AbstractShaderProgram::bindAttributeLocation(), it's +rather easy, as you can simply use the @ref GL::Attribute::Location of given +attribute: + +@snippet MagnumShaders-gl.cpp GenericGL-custom-bind + +For attribute location defined directly in shader code (which is the +recommended way unless you need compatibility with WebGL 1.0 and OpenGL ES +2.0), the attribute locations can be propagated using a preprocessor define. +For example: + +@snippet MagnumShaders-gl.cpp GenericGL-custom-preprocessor + +Then, the attribute definition in a shader will look like this: + +@code{.glsl} +layout(location = POSITION_ATTRIBUTE_LOCATION) in vec3 position; +layout(location = NORMAL_ATTRIBUTE_LOCATION) in vec3 normal; +@endcode + +@see @ref shaders, @ref GenericGL2D, @ref GenericGL3D +*/ +#ifndef DOXYGEN_GENERATING_OUTPUT +template struct GenericGL; +#else +template struct GenericGL { + /* Keep consistent with generic.glsl and the real definitions below */ + + enum: UnsignedInt { + /** + * Color shader output. Present always, expects three- or + * four-component floating-point or normalized buffer attachment. + */ + ColorOutput = 0, + + #ifndef MAGNUM_TARGET_GLES2 + /** + * Object ID shader output. Expects a single-component unsigned + * integral attachment. + * @requires_gl30 Extension @gl_extension{EXT,texture_integer} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. + */ + ObjectIdOutput = 1 + #endif + }; + + /** + * @brief Vertex position + * + * @ref Magnum::Vector2 "Vector2" in 2D and @ref Magnum::Vector3 "Vector3" + * in 3D. Corresponds to @ref Trade::MeshAttribute::Position. + */ + typedef GL::Attribute<0, T> Position; + + /** + * @brief 2D texture coordinates + * + * @ref Magnum::Vector2 "Vector2". Corresponds to + * @ref Trade::MeshAttribute::TextureCoordinates. + */ + typedef GL::Attribute<1, Vector2> TextureCoordinates; + + /** + * @brief Three-component vertex color + * + * @ref Magnum::Color3. Use either this or the @ref Color4 attribute. + * Corresponds to @ref Trade::MeshAttribute::Color. + */ + typedef GL::Attribute<2, Magnum::Color3> Color3; + + /** + * @brief Four-component vertex color + * + * @ref Magnum::Color4. Use either this or the @ref Color3 attribute. + * Corresponds to @ref Trade::MeshAttribute::Color. + */ + typedef GL::Attribute<2, Magnum::Color4> Color4; + + /** + * @brief Vertex tangent + * @m_since{2019,10} + * + * @ref Magnum::Vector3 "Vector3", defined only in 3D. Use either this or + * the @ref Tangent4 attribute. Corresponds to + * @ref Trade::MeshAttribute::Tangent. + */ + typedef GL::Attribute<3, Vector3> Tangent; + + /** + * @brief Vertex tangent with a bitangent sign + * @m_since{2020,06} + * + * @ref Magnum::Vector4 "Vector4", defined only in 3D. The last component + * is a sign value (@cpp -1.0f @ce or @cpp +1.0f @ce) defining handedness + * of the tangent basis. Reconstructing the @ref Bitangent attribute can be + * then done like this: + * + * @snippet MagnumTrade.cpp MeshAttribute-bitangent-from-tangent + * + * Use either this or the @ref Tangent attribute. Corresponds to + * @ref Trade::MeshAttribute::Tangent. + */ + typedef GL::Attribute<3, Vector4> Tangent4; + + /** + * @brief Vertex bitangent + * @m_since{2020,06} + * + * @ref Magnum::Vector3 "Vector3", defined only in 3D. For better storage + * efficiency, the bitangent can be also reconstructed from the normal and + * tangent, see @ref Tangent4 for more information. Corresponds to + * @ref Trade::MeshAttribute::Bitangent. + * + * This attribute conflicts with @ref ObjectId, if you want to use both + * instanced object ID and bitangents, you need to reconstruct them from + * @ref Tangent4 instead. + */ + typedef GL::Attribute<4, Vector3> Bitangent; + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief (Instanced) object ID + * @m_since{2020,06} + * + * @ref Magnum::UnsignedInt "UnsignedInt". Corresponds to + * @ref Trade::MeshAttribute::ObjectId. + * + * This attribute conflicts with @ref Bitangent, if you want to use both + * instanced object ID and bitangents, you need to reconstruct them from + * @ref Tangent4 instead. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in shaders, + * which is not available in OpenGL ES 2.0 or WebGL 1.0. + */ + typedef GL::Attribute<4, UnsignedInt> ObjectId; + #endif + + /* Index 4 also used by MeshVisualizer::VertexIndex (reusing ObjectId). Not + making it generic yet, as its use case is limited to a single shader, + and even there it's just a fallback for platforms w/o gl_VertexID. */ + + /** + * @brief Vertex normal + * + * @ref Magnum::Vector3 "Vector3", defined only in 3D. Corresponds to + * @ref Trade::MeshAttribute::Normal. + */ + typedef GL::Attribute<5, Vector3> Normal; + + /* 6, 7 reserved for vertex weights / bone IDs */ + + /** + * @brief (Instanced) transformation matrix + * @m_since{2020,06} + * + * @ref Magnum::Matrix3 "Matrix3" in 2D and @ref Magnum::Matrix4 "Matrix4" + * in 3D. Currently doesn't have a corresponding @ref Trade::MeshAttribute. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + */ + typedef GL::Attribute<8, T> TransformationMatrix; + + /* 9, 10, 11 occupied by TransformationMatrix */ + + /** + * @brief (Instanced) normal matrix + * @m_since{2020,06} + * + * @ref Magnum::Matrix3 "Matrix3x3", defined only in 3D. Currently doesn't + * have a corresponding @ref Trade::MeshAttribute. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + */ + typedef GL::Attribute<12, Matrix3x3> NormalMatrix; + + /* 13, 14 occupied by NormalMatrix */ + + /** + * @brief (Instanced) texture offset + * @m_since{2020,06} + * + * @ref Magnum::Vector2 "Vector2". Currently doesn't have a corresponding + * @ref Trade::MeshAttribute. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + */ + typedef GL::Attribute<15, Vector2> TextureOffset; +}; +#endif + +/** +@brief Generic 2D OpenGL shader definition +@m_since_latest +*/ +typedef GenericGL<2> GenericGL2D; + +/** +@brief Generic 3D OpenGL shader definition +@m_since_latest +*/ +typedef GenericGL<3> GenericGL3D; + +#ifndef DOXYGEN_GENERATING_OUTPUT +struct BaseGenericGL { + enum: UnsignedInt { + ColorOutput = 0, + #ifndef MAGNUM_TARGET_GLES2 + ObjectIdOutput = 1 + #endif + }; + + typedef GL::Attribute<1, Vector2> TextureCoordinates; + typedef GL::Attribute<2, Magnum::Color3> Color3; + typedef GL::Attribute<2, Magnum::Color4> Color4; + #ifndef MAGNUM_TARGET_GLES2 + typedef GL::Attribute<4, UnsignedInt> ObjectId; + #endif + + typedef GL::Attribute<15, Vector2> TextureOffset; +}; + +template<> struct GenericGL<2>: BaseGenericGL { + typedef GL::Attribute<0, Vector2> Position; + /* 1, 2 used by TextureCoordinates and Color */ + + typedef GL::Attribute<8, Matrix3> TransformationMatrix; + /* 9, 10 occupied by TransformationMatrix */ + /* 15 used by TextureOffset */ +}; + +template<> struct GenericGL<3>: BaseGenericGL { + typedef GL::Attribute<0, Vector3> Position; + /* 1, 2 used by TextureCoordinates and Color */ + typedef GL::Attribute<3, Vector3> Tangent; + typedef GL::Attribute<3, Vector4> Tangent4; + typedef GL::Attribute<4, Vector3> Bitangent; /* also ObjectId */ + typedef GL::Attribute<5, Vector3> Normal; + /* 6, 7 reserved for vertex weights / bone IDs */ + + typedef GL::Attribute<8, Matrix4> TransformationMatrix; + /* 9, 10, 11 occupied by TransformationMatrix */ + typedef GL::Attribute<12, Matrix3x3> NormalMatrix; + /* 13, 14 occupied by NormalMatrix */ + /* 15 used by TextureOffset */ +}; +#endif + +#ifdef MAGNUM_BUILD_DEPRECATED +/* Deprecated aliases present here instead of GenericGL.h, as a lot of existing + code relies on these being transitively included from Phong.h etc., and + there are no forward declarations in Shaders.h as the type is never used + like that. While we *could* include Generic.h from Phong.h, we'd have to + also temporarily disable the CORRADE_DEPRECATED_FILE() macro there and it's + more pain than it's worth. */ + +/** @brief @copybrief GenericGL + * @m_deprecated_since_latest Use @ref GenericGL instead. + */ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using Generic CORRADE_DEPRECATED_ALIAS("use GenericGL instead") = GenericGL; +#endif + +/** @brief @copybrief GenericGL2D + * @m_deprecated_since_latest Use @ref GenericGL2D instead. + */ +typedef CORRADE_DEPRECATED("use GenericGL2D instead") GenericGL2D Generic2D; + +/** @brief @copybrief GenericGL3D + * @m_deprecated_since_latest Use @ref GenericGL3D instead. + */ +typedef CORRADE_DEPRECATED("use GenericGL3D instead") GenericGL3D Generic3D; +#endif + +}} + +#endif diff --git a/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h b/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h index 2802e4d0b..a96613ab4 100644 --- a/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h +++ b/src/Magnum/Shaders/Implementation/CreateCompatibilityShader.h @@ -35,7 +35,7 @@ "static symbol not used" warning when using this file for TextureTools */ #if defined(MAGNUM_BUILD_STATIC) && defined(MAGNUM_SHADERS_EXPORT) static void importShaderResources() { - CORRADE_RESOURCE_INITIALIZE(MagnumShaders_RCS) + CORRADE_RESOURCE_INITIALIZE(MagnumShaders_RESOURCES_GL) } #endif diff --git a/src/Magnum/Shaders/MeshVisualizer.h b/src/Magnum/Shaders/MeshVisualizer.h index e66bca3a1..3a725bdef 100644 --- a/src/Magnum/Shaders/MeshVisualizer.h +++ b/src/Magnum/Shaders/MeshVisualizer.h @@ -25,1019 +25,45 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file - * @brief Class @ref Magnum::Shaders::MeshVisualizer2D, @ref Magnum::Shaders::MeshVisualizer3D + * @brief Typedef @ref Magnum::Shaders::MeshVisualizer2D, @ref Magnum::Shaders::MeshVisualizer3D + * @m_deprecated_since_latest Use @ref Magnum/Shaders/MeshVisualizerGL.h and + * the @ref Magnum::Shaders::MeshVisualizerGL2D "MeshVisualizerGL2D" / + * @ref Magnum::Shaders::MeshVisualizerGL3D "MeshVisualizerGL3D" class + * instead */ +#endif -#include - -#include "Magnum/DimensionTraits.h" -#include "Magnum/GL/AbstractShaderProgram.h" -#include "Magnum/Shaders/Generic.h" -#include "Magnum/Shaders/visibility.h" - -namespace Magnum { namespace Shaders { - -namespace Implementation { - -class MAGNUM_SHADERS_EXPORT MeshVisualizerBase: public GL::AbstractShaderProgram { - protected: - enum class FlagBase: UnsignedShort { - /* Unlike the public Wireframe flag, this one doesn't include - NoGeometryShader on ES2 as that would make the checks too - complex */ - Wireframe = 1 << 0, - NoGeometryShader = 1 << 1, - #ifndef MAGNUM_TARGET_GLES2 - InstancedObjectId = 1 << 2, - VertexId = 1 << 3, - PrimitiveId = 1 << 4, - PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId - #endif - }; - typedef Containers::EnumSet FlagsBase; - - CORRADE_ENUMSET_FRIEND_OPERATORS(FlagsBase) - - explicit MeshVisualizerBase(FlagsBase flags); - explicit MeshVisualizerBase(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - - MAGNUM_SHADERS_LOCAL GL::Version setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const; - - MeshVisualizerBase& setColor(const Color4& color); - MeshVisualizerBase& setWireframeColor(const Color4& color); - MeshVisualizerBase& setWireframeWidth(Float width); - #ifndef MAGNUM_TARGET_GLES2 - MeshVisualizerBase& setColorMapTransformation(Float offset, Float scale); - MeshVisualizerBase& bindColorMapTexture(GL::Texture2D& texture); - #endif - - /* Prevent accidentally calling irrelevant functions */ - #ifndef MAGNUM_TARGET_GLES - using GL::AbstractShaderProgram::drawTransformFeedback; - #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - using GL::AbstractShaderProgram::dispatchCompute; - #endif - - FlagsBase _flags; - Int _colorUniform{1}, - _wireframeColorUniform{2}, - _wireframeWidthUniform{3}, - _smoothnessUniform{4}, - _viewportSizeUniform{5}; - #ifndef MAGNUM_TARGET_GLES2 - Int _colorMapOffsetScaleUniform{6}; - #endif -}; - -} - -/** -@brief 2D mesh visualization shader -@m_since{2020,06} - -Visualizes wireframe, per-vertex/per-instance object ID or primitive ID of 2D -meshes. You need to provide the @ref Position attribute in your triangle mesh. -Use @ref setTransformationProjectionMatrix(), @ref setColor() and others to -configure the shader. - -@m_class{m-row} - -@parblock - -@m_div{m-col-m-4 m-col-t-6 m-push-m-2 m-nopadt m-nopadx} -@image html shaders-meshvisualizer2d.png width=256px -@m_enddiv - -@m_div{m-col-m-4 m-col-t-6 m-push-m-2 m-nopadt m-nopadx} -@image html shaders-meshvisualizer2d-primitiveid.png width=256px -@m_enddiv - -@endparblock - -The shader expects that you enable wireframe visualization by passing an -appropriate @ref Flag to the constructor --- there's no default behavior with -nothing enabled. The shader is a 2D variant of @ref MeshVisualizer3D with -mostly identical workflow. See its documentation for more information. -*/ -class MAGNUM_SHADERS_EXPORT MeshVisualizer2D: public Implementation::MeshVisualizerBase { - public: - /** - * @brief Vertex position - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector2 "Vector2". - */ - typedef typename Generic2D::Position Position; - - /** - * @brief Vertex index - * - * See @ref MeshVisualizer3D::VertexIndex for more information. - */ - typedef GL::Attribute<4, Float> VertexIndex; - - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief (Instanced) object ID - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. - * Used only if @ref Flag::InstancedObjectId is set. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. - */ - typedef Generic3D::ObjectId ObjectId; - #endif - - enum: UnsignedInt { - /** - * Color shader output. @ref shaders-generic "Generic output", - * present always. Expects three- or four-component floating-point - * or normalized buffer attachment. - */ - ColorOutput = Generic2D::ColorOutput - }; - - /** - * @brief Flag - * - * @see @ref Flags, @ref MeshVisualizer2D() - */ - enum class Flag: UnsignedShort { - /** - * Visualize wireframe. On OpenGL ES 2.0 and WebGL this also - * enables @ref Flag::NoGeometryShader. - */ - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - Wireframe = 1 << 0, - #else - Wireframe = (1 << 0) | (1 << 1), - #endif - - /** - * Don't use a geometry shader for wireframe visualization. If - * enabled, you might need to provide also the @ref VertexIndex - * attribute in the mesh. On OpenGL ES 2.0 and WebGL enabled - * alongside @ref Flag::Wireframe. - */ - NoGeometryShader = 1 << 1, - - #ifndef MAGNUM_TARGET_GLES2 - /** @copydoc MeshVisualizer3D::Flag::InstancedObjectId */ - InstancedObjectId = 1 << 2, - - /** @copydoc MeshVisualizer3D::Flag::VertexId */ - VertexId = 1 << 3, - - #ifndef MAGNUM_TARGET_WEBGL - /** @copydoc MeshVisualizer3D::Flag::PrimitiveId */ - PrimitiveId = 1 << 4, - #endif - - /** @copydoc MeshVisualizer3D::Flag::PrimitiveIdFromVertexId */ - #ifndef MAGNUM_TARGET_WEBGL - PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId - #else - PrimitiveIdFromVertexId = (1 << 5)|(1 << 4) - #endif - #endif - }; - - /** @brief Flags */ - typedef Containers::EnumSet Flags; - - /** - * @brief Constructor - * @param flags Flags - * - * At least @ref Flag::Wireframe is expected to be enabled. - */ - explicit MeshVisualizer2D(Flags flags); - - /** - * @brief Construct without creating the underlying OpenGL object - * - * The constructed instance is equivalent to a moved-from state. Useful - * in cases where you will overwrite the instance later anyway. Move - * another object over it to make it useful. - * - * This function can be safely used for constructing (and later - * destructing) objects even without any OpenGL context being active. - * However note that this is a low-level and a potentially dangerous - * API, see the documentation of @ref NoCreate for alternatives. - */ - explicit MeshVisualizer2D(NoCreateT) noexcept: Implementation::MeshVisualizerBase{NoCreate} {} - - /** @brief Copying is not allowed */ - MeshVisualizer2D(const MeshVisualizer2D&) = delete; - - /** @brief Move constructor */ - MeshVisualizer2D(MeshVisualizer2D&&) noexcept = default; - - /** @brief Copying is not allowed */ - MeshVisualizer2D& operator=(const MeshVisualizer2D&) = delete; - - /** @brief Move assignment */ - MeshVisualizer2D& operator=(MeshVisualizer2D&&) noexcept = default; - - /** @brief Flags */ - Flags flags() const { - return Flag(UnsignedShort(Implementation::MeshVisualizerBase::_flags)); - } - - /** - * @brief Set transformation and projection matrix - * @return Reference to self (for method chaining) - * - * Initial value is an identity matrix. - */ - MeshVisualizer2D& setTransformationProjectionMatrix(const Matrix3& matrix); - - /** - * @brief Set viewport size - * @return Reference to self (for method chaining) - * - * Has effect only if @ref Flag::Wireframe is enabled and geometry - * shaders are used, otherwise it does nothing. Initial value is a zero - * vector. - */ - MeshVisualizer2D& setViewportSize(const Vector2& size); - - /** - * @brief Set base object color - * @return Reference to self (for method chaining) - * - * Initial value is @cpp 0xffffffff_rgbaf @ce. Expects that either - * @ref Flag::Wireframe or @ref Flag::InstancedObjectId / - * @ref Flag::PrimitiveId is enabled. In case of the latter, the color - * is multiplied with the color map coming from - * @ref bindColorMapTexture(). - */ - MeshVisualizer2D& setColor(const Color4& color) { - return static_cast(Implementation::MeshVisualizerBase::setColor(color)); - } - - /** - * @brief Set wireframe color - * @return Reference to self (for method chaining) - * - * Initial value is @cpp 0x000000ff_rgbaf @ce. Expects that - * @ref Flag::Wireframe is enabled. - */ - MeshVisualizer2D& setWireframeColor(const Color4& color) { - return static_cast(Implementation::MeshVisualizerBase::setWireframeColor(color)); - } - - /** - * @brief Set wireframe width - * @return Reference to self (for method chaining) - * - * Value is in screen space (depending on @ref setViewportSize()), - * initial value is @cpp 1.0f @ce. Expects that @ref Flag::Wireframe is - * enabled. - */ - MeshVisualizer2D& setWireframeWidth(Float width) { - return static_cast(Implementation::MeshVisualizerBase::setWireframeWidth(width)); - } - - #ifndef MAGNUM_TARGET_GLES2 - /** @copydoc MeshVisualizer3D::setColorMapTransformation() */ - MeshVisualizer2D& setColorMapTransformation(Float offset, Float scale) { - return static_cast(Implementation::MeshVisualizerBase::setColorMapTransformation(offset, scale)); - } - - /** @copydoc MeshVisualizer3D::bindColorMapTexture() */ - MeshVisualizer2D& bindColorMapTexture(GL::Texture2D& texture) { - return static_cast(Implementation::MeshVisualizerBase::bindColorMapTexture(texture)); - } - #endif - - /** - * @brief Set line smoothness - * @return Reference to self (for method chaining) - * - * Value is in screen space (depending on @ref setViewportSize()), - * initial value is @cpp 2.0f @ce. Expects that @ref Flag::Wireframe is - * enabled. - */ - MeshVisualizer2D& setSmoothness(Float smoothness); - - private: - Int _transformationProjectionMatrixUniform{0}; -}; - -/** -@brief 3D mesh visualization shader - -Visualizes wireframe, per-vertex/per-instance object ID, primitive ID or -tangent space of 3D meshes. You need to provide the @ref Position attribute in -your triangle mesh at the very least. Use @ref setTransformationProjectionMatrix(), -@ref setColor() and others to configure the shader. - -@m_class{m-row} - -@parblock - -@m_div{m-col-m-4 m-col-t-6 m-push-m-2 m-text-center m-nopadt m-nopadx} -@image html shaders-meshvisualizer3d.png width=256px -@ref Shaders-MeshVisualizer-wireframe, \n -@ref Shaders-MeshVisualizer-tbn -@m_enddiv - -@m_div{m-col-m-4 m-col-t-6 m-push-m-2 m-text-center m-nopadt m-nopadx} -@image html shaders-meshvisualizer3d-primitiveid.png width=256px -@ref Shaders-MeshVisualizer-object-id -@m_enddiv - -@endparblock - -The shader expects that you enable wireframe visualization, tangent space -visualization or object/primitive ID visualization by passing an appropriate -@ref Flag to the constructor --- there's no default behavior with nothing -enabled. - -@section Shaders-MeshVisualizer-wireframe Wireframe visualization - -Wireframe visualization is done by enabling @ref Flag::Wireframe. It is done -either using geometry shaders or with help of additional vertex information. If -you have geometry shaders available, you don't need to do anything else except -calling @ref setViewportSize() to correctly size the wireframe --- without -this, the mesh will be rendered in a single color. - -@requires_gl32 Extension @gl_extension{ARB,geometry_shader4} for wireframe - rendering using geometry shaders. -@requires_es_extension Extension @gl_extension{EXT,geometry_shader} for - wireframe rendering using geometry shaders. - -If you don't have geometry shaders, you need to enable @ref Flag::NoGeometryShader -(done by default in OpenGL ES 2.0) and use only **non-indexed** triangle meshes -(see @ref MeshTools::duplicate() for a possible solution). Additionaly, if you -have OpenGL < 3.1 or OpenGL ES 2.0, you need to provide also the -@ref VertexIndex attribute. - -@requires_gles30 Extension @gl_extension{OES,standard_derivatives} for - wireframe rendering without geometry shaders. - -If using geometry shaders on OpenGL ES, @gl_extension{NV,shader_noperspective_interpolation} -is optionally used for improving line appearance. On desktop OpenGL this is -done implicitly. - -If you want to render just the wireframe on top of an existing mesh, call -@ref setColor() with @cpp 0x00000000_rgbaf @ce. Alpha / transparency is -supported by the shader implicitly, but to have it working on the framebuffer, -you need to enable @ref GL::Renderer::Feature::Blending and set up the blending -function. See @ref GL::Renderer::setBlendFunction() for details. - -@subsection Shaders-MeshVisualizer-wireframe-geom Example setup with a geometry shader (desktop GL, OpenGL ES 3.2) - -Common mesh setup: - -@snippet MagnumShaders.cpp MeshVisualizer-usage-geom1 - -Common rendering setup: - -@snippet MagnumShaders.cpp MeshVisualizer-usage-geom2 - -@subsection Shaders-MeshVisualizer-wireframe-no-geom Example setup for indexed meshes without a geometry shader - -The vertices have to be converted to a non-indexed array first. Mesh setup: - -@snippet MagnumShaders.cpp MeshVisualizer-usage-no-geom1 - -Rendering setup: - -@snippet MagnumShaders.cpp MeshVisualizer-usage-no-geom2 - -@subsection Shaders-MeshVisualizer-usage-wireframe-no-geom-old Wireframe visualization of non-indexed meshes without a geometry shader on older hardware - -You need to provide also the @ref VertexIndex attribute. Mesh setup *in -addition to the above*: - -@snippet MagnumShaders.cpp MeshVisualizer-usage-no-geom-old - -Rendering setup the same as above. - -@section Shaders-MeshVisualizer-tbn Tangent space visualization - -On platforms with geometry shaders (desktop GL, OpenGL ES 3.2), the shader is -able to visualize tangents, bitangent and normal direction via colored lines -coming out of vertices (red, green and blue for tangent, bitangent and normal, respectively). This can be enabled together with wireframe visualization, -however note that when both are enabled, the lines are not antialiased to avoid -depth ordering artifacts. - -For tangents and normals, you need to provide the @ref Tangent and @ref Normal -attributes and enable @ref Flag::TangentDirection and -@ref Flag::NormalDirection, respectively. If any of the attributes isn't -present, its data are implicitly zero and thus the direction isn't shown --- -which means you don't need to worry about having two active variants of the -shader and switching between either depending on whether tangents are present -or not. - -For bitangents however, there are two possible representations --- the more -efficient one is via a fourth component in the tangent attribute that -indicates tangent space handedness, in which case you'll be using the -@ref Tangent4 attribute instead of @ref Tangent, and enable -@ref Flag::BitangentFromTangentDirection. The other, more obvious but less -efficient representation, is a dedicated @ref Bitangent attribute (in which -case you'll enable @ref Flag::BitangentDirection). Note that these two are -mutually exclusive, so you need to choose either of them based on what given -mesh contains. Example for the first case: - -@snippet MagnumShaders.cpp MeshVisualizer-usage-tbn1 - -Rendering setup: - -@snippet MagnumShaders.cpp MeshVisualizer-usage-tbn2 - -@section Shaders-MeshVisualizer-object-id Object, vertex and primitive ID visualization - -If the mesh contains a per-vertex (or instanced) @ref ObjectId, it can be -visualized by enabling @ref Flag::InstancedObjectId. For the actual -visualization you need to provide a color map using @ref bindColorMapTexture() -and use @ref setColorMapTransformation() to map given range of discrete IDs to -the @f$ [0, 1] @f$ texture range. Various colormap presets are in the -@ref DebugTools::ColorMap namespace. Example usage: - -@snippet MagnumShaders.cpp MeshVisualizer-usage-object-id - -If you enable @ref Flag::VertexId, the shader will use the color map to -visualize how are vertices shared among primitives. That's useful for -inspecting mesh connectivity --- primitives sharing vertices will have a smooth -color map transition while duplicated vertices will cause a sharp edge. This -relies on the @glsl gl_VertexID @ce GLSL builtin. - -The @ref Flag::PrimitiveId then visualizes the order in which primitives are -drawn. That's useful for example to see to see how well is the mesh optimized -for a post-transform vertex cache. This by default relies on the @glsl gl_PrimitiveID @ce GLSL builtin; with @ref Flag::PrimitiveIdFromVertexId it's -emulated using @glsl gl_VertexID @ce, expecting you to draw a non-indexed -triangle mesh. You can use @ref MeshTools::duplicate() (and potentially -@ref MeshTools::generateIndices()) to conveniently convert the mesh to a -non-indexed @ref MeshPrimitive::Triangles. - -@requires_gl32 The `gl_PrimitiveID` shader variable is not available on OpenGL - 3.1 and lower. -@requires_gl30 The `gl_VertexID` shader variable is not available on OpenGL - 2.1. -@requires_gles32 The `gl_PrimitiveID` shader variable is not available on - OpenGL ES 3.1 and lower. -@requires_gles30 The `gl_VertexID` shader variable is not available on OpenGL - ES 2.0. -@requires_gles `gl_PrimitiveID` is not available in WebGL. -@requires_webgl20 `gl_VertexID` is not available in WebGL 1.0. - -@see @ref shaders, @ref MeshVisualizer2D -@todo Understand and add support wireframe width/smoothness without GS -*/ -class MAGNUM_SHADERS_EXPORT MeshVisualizer3D: public Implementation::MeshVisualizerBase { - public: - /** - * @brief Vertex position - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector3 "Vector3". - */ - typedef typename Generic3D::Position Position; - - /** - * @brief Tangent direction - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4 - * attribute. Used only if @ref Flag::TangentDirection is enabled. - */ - typedef typename Generic3D::Tangent Tangent; - - /** - * @brief Tangent direction with a bitangent sign - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector4 "Vector4". Use either this or the @ref Tangent - * attribute. Used only if @ref Flag::TangentDirection or - * @ref Flag::BitangentFromTangentDirection is enabled. - */ - typedef typename Generic3D::Tangent4 Tangent4; - - /** - * @brief Bitangent direction - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4 - * attribute. Used only if @ref Flag::BitangentDirection is enabled. - */ - typedef typename Generic3D::Bitangent Bitangent; - - /** - * @brief Normal direction - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector3 "Vector3". Used only if - * @ref Flag::NormalDirection is enabled. - */ - typedef typename Generic3D::Normal Normal; - - /** - * @brief Vertex index - * - * @ref Magnum::Float "Float", used only in OpenGL < 3.1 and OpenGL ES - * 2.0 if @ref Flag::Wireframe is enabled. This attribute (modulo 3) - * specifies index of given vertex in triangle, i.e. @cpp 0.0f @ce for - * first, @cpp 1.0f @ce for second, @cpp 2.0f @ce for third. In OpenGL - * 3.1, OpenGL ES 3.0 and newer this value is provided via the - * @cb{.glsl} gl_VertexID @ce shader builtin, so the attribute is not - * needed. - * - * @note This attribute uses the same slot as @ref Generic::ObjectId, - * but since Object ID is available only on ES3+ and vertex index - * is used only on ES2 contexts without @glsl gl_VertexID @ce, - * there should be no conflict between these two. - */ - typedef GL::Attribute<4, Float> VertexIndex; - - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief (Instanced) object ID - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. - * Used only if @ref Flag::InstancedObjectId is set. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. - */ - typedef Generic3D::ObjectId ObjectId; - #endif - - enum: UnsignedInt { - /** - * Color shader output. @ref shaders-generic "Generic output", - * present always. Expects three- or four-component floating-point - * or normalized buffer attachment. - */ - ColorOutput = Generic3D::ColorOutput - }; - - /** - * @brief Flag - * - * @see @ref Flags, @ref MeshVisualizer() - */ - enum class Flag: UnsignedShort { - /** - * Visualize wireframe. On OpenGL ES 2.0 and WebGL this also - * enables @ref Flag::NoGeometryShader. - */ - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - Wireframe = 1 << 0, - #else - Wireframe = (1 << 0) | (1 << 1), - #endif - - /** - * Don't use a geometry shader for wireframe visualization. If - * enabled, you might need to provide also the @ref VertexIndex - * attribute in the mesh. On OpenGL ES 2.0 and WebGL enabled - * alongside @ref Flag::Wireframe. - * - * Mutually exclusive with @ref Flag::TangentDirection, - * @ref Flag::BitangentFromTangentDirection, - * @ref Flag::BitangentDirection and @ref Flag::NormalDirection --- - * those need a geometry shader always. - */ - NoGeometryShader = 1 << 1, - - #ifndef MAGNUM_TARGET_GLES2 - /** - * Visualize instanced object ID. You need to provide the - * @ref ObjectId attribute in the mesh. Mutually exclusive with - * @ref Flag::VertexId and @ref Flag::PrimitiveId. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL - * 1.0. - * @m_since{2020,06} - */ - InstancedObjectId = 1 << 2, - - /** - * Visualize vertex ID (@cpp gl_VertexID @ce). Useful for - * visualizing mesh connectivity --- primitives sharing vertices - * will have a smooth color map transition while duplicated - * vertices will cause a sharp edge. Mutually exclusive with - * @ref Flag::InstancedObjectId and @ref Flag::PrimitiveId. - * @requires_gl30 The `gl_VertexID` shader variable is not - * available on OpenGL 2.1. - * @requires_gles30 The `gl_VertexID` shader variable is not - * available on OpenGL ES 2.0. - * @requires_webgl20 `gl_VertexID` is not available in WebGL 1.0. - * @m_since{2020,06} - */ - VertexId = 1 << 3, - - #ifndef MAGNUM_TARGET_WEBGL - /** - * Visualize primitive ID (@cpp gl_PrimitiveID @ce). Useful for - * visualizing how well is the mesh optimized for a post-transform - * vertex cache. Mutually exclusive with - * @ref Flag::InstancedObjectId and @ref Flag::VertexId. See also - * @ref Flag::PrimitiveIdFromVertexId. - * @requires_gl32 The `gl_PrimitiveID` shader variable is not - * available on OpenGL 3.1 and lower. - * @requires_gles30 Not defined in OpenGL ES 2.0. - * @requires_gles32 The `gl_PrimitiveID` shader variable is not - * available on OpenGL ES 3.1 and lower. - * @requires_gles `gl_PrimitiveID` is not available in WebGL. - * @m_since{2020,06} - */ - PrimitiveId = 1 << 4, - #endif - - /** - * Visualize primitive ID on a non-indexed triangle mesh using - * @cpp gl_VertexID/3 @ce. Implicitly enables - * @ref Flag::PrimitiveId, mutually exclusive with - * @ref Flag::InstancedObjectId. Usable on OpenGL < 3.2, - * OpenGL ES < 3.2 and WebGL where @cpp gl_PrimitiveID @ce is not - * available. - * @requires_gl30 The `gl_VertexID` shader variable is not - * available on OpenGL 2.1. - * @requires_gles30 The `gl_VertexID` shader variable is not - * available on OpenGL ES 2.0. - * @requires_webgl20 `gl_VertexID` is not available in WebGL 1.0. - * @m_since{2020,06} - */ - #ifndef MAGNUM_TARGET_WEBGL - PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId, - #else - PrimitiveIdFromVertexId = (1 << 5)|(1 << 4), - #endif - #endif - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - /** - * Visualize tangent direction with red lines pointing out of - * vertices. You need to provide the @ref Tangent or @ref Tangent4 - * attribute in the mesh. Mutually exclusive with - * @ref Flag::NoGeometryShader (as this needs a geometry shader - * always). - * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} - * @requires_gles30 Not defined in OpenGL ES 2.0. - * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / - * @gl_extension{EXT,geometry_shader} - * @requires_gles Geometry shaders are not available in WebGL. - * @m_since{2020,06} - */ - TangentDirection = 1 << 6, - - /** - * Visualize bitangent direction with green lines pointing out of - * vertices. You need to provide both @ref Normal and @ref Tangent4 - * attributes in the mesh, alternatively you can provide the - * @ref Bitangent attribute and enable - * @ref Flag::BitangentDirection instead. Mutually exclusive with - * @ref Flag::NoGeometryShader (as this needs a geometry shader - * always). - * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} - * @requires_gles30 Not defined in OpenGL ES 2.0. - * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / - * @gl_extension{EXT,geometry_shader} - * @requires_gles Geometry shaders are not available in WebGL. - * @m_since{2020,06} - */ - BitangentFromTangentDirection = 1 << 7, - - /** - * Visualize bitangent direction with green lines pointing out of - * vertices. You need to provide the @ref Bitangent attribute in - * the mesh, alternatively you can provide both @ref Normal and - * @ref Tangent4 attributes and enable - * @ref Flag::BitangentFromTangentDirection instead. Mutually - * exclusive with @ref Flag::NoGeometryShader (as this needs a - * geometry shader always). - * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} - * @requires_gles30 Not defined in OpenGL ES 2.0. - * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / - * @gl_extension{EXT,geometry_shader} - * @requires_gles Geometry shaders are not available in WebGL. - * @m_since{2020,06} - */ - BitangentDirection = 1 << 8, - - /** - * Visualize normal direction with blue lines pointing out of - * vertices. You need to provide the @ref Normal attribute in the - * mesh. Mutually exclusive with @ref Flag::NoGeometryShader (as - * this needs a geometry shader always). - * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} - * @requires_gles30 Not defined in OpenGL ES 2.0. - * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / - * @gl_extension{EXT,geometry_shader} - * @requires_gles Geometry shaders are not available in WebGL. - * @m_since{2020,06} - */ - NormalDirection = 1 << 9 - #endif - }; - - /** @brief Flags */ - typedef Containers::EnumSet Flags; - - /** - * @brief Constructor - * @param flags Flags - * - * At least @ref Flag::Wireframe or one of @ref Flag::TangentDirection, - * @ref Flag::BitangentFromTangentDirection, - * @ref Flag::BitangentDirection, @ref Flag::NormalDirection is - * expected to be enabled. - */ - explicit MeshVisualizer3D(Flags flags); - - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @brief Constructor - * @m_deprecated_since{2020,06} Use @ref MeshVisualizer3D(Flags) instead. - */ - explicit CORRADE_DEPRECATED("use MeshVisualizer3D(Flags) instead") MeshVisualizer3D(): MeshVisualizer3D{{}} {} - #endif - - /** - * @brief Construct without creating the underlying OpenGL object - * - * The constructed instance is equivalent to a moved-from state. Useful - * in cases where you will overwrite the instance later anyway. Move - * another object over it to make it useful. - * - * This function can be safely used for constructing (and later - * destructing) objects even without any OpenGL context being active. - * However note that this is a low-level and a potentially dangerous - * API, see the documentation of @ref NoCreate for alternatives. - */ - explicit MeshVisualizer3D(NoCreateT) noexcept: Implementation::MeshVisualizerBase{NoCreate} {} - - /** @brief Copying is not allowed */ - MeshVisualizer3D(const MeshVisualizer3D&) = delete; - - /** @brief Move constructor */ - MeshVisualizer3D(MeshVisualizer3D&&) noexcept = default; - - /** @brief Copying is not allowed */ - MeshVisualizer3D& operator=(const MeshVisualizer3D&) = delete; - - /** @brief Move assignment */ - MeshVisualizer3D& operator=(MeshVisualizer3D&&) noexcept = default; - - /** @brief Flags */ - Flags flags() const { - return Flag(UnsignedShort(Implementation::MeshVisualizerBase::_flags)); - } - - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @brief Set transformation and projection matrix - * @m_deprecated_since{2020,06} Use @ref setTransformationMatrix() and - * @ref setProjectionMatrix() instead. - */ - CORRADE_DEPRECATED("use setTransformationMatrix() and setProjectionMatrix() instead") MeshVisualizer3D& setTransformationProjectionMatrix(const Matrix4& matrix) { - /* Keep projection at identity, which should still work for - wireframe (but of course not for TBN visualization) */ - return setTransformationMatrix(matrix); - } - #endif - - /** - * @brief Set transformation matrix - * @return Reference to self (for method chaining) - * - * Initial value is an identity matrix. - */ - MeshVisualizer3D& setTransformationMatrix(const Matrix4& matrix); - - /** - * @brief Set projection matrix - * @return Reference to self (for method chaining) - * - * Initial value is an identity matrix. (i.e., an orthographic - * projection of the default @f$ [ -\boldsymbol{1} ; \boldsymbol{1} ] @f$ - * cube). - */ - MeshVisualizer3D& setProjectionMatrix(const Matrix4& matrix); - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - /** - * @brief Set transformation matrix - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * Expects that @ref Flag::TangentDirection, - * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is - * enabled. The matrix doesn't need to be normalized, as - * renormalization is done per-fragment anyway. - * Initial value is an identity matrix. - * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} - * @requires_gles30 Not defined in OpenGL ES 2.0. - * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / - * @gl_extension{EXT,geometry_shader} - * @requires_gles Geometry shaders are not available in WebGL. - */ - MeshVisualizer3D& setNormalMatrix(const Matrix3x3& matrix); - #endif - - /** - * @brief Set viewport size - * @return Reference to self (for method chaining) - * - * Has effect only if @ref Flag::Wireframe is enabled and geometry - * shaders are used; or if @ref Flag::TangentDirection, - * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is - * enabled, otherwise it does nothing. Initial value is a zero vector. - */ - MeshVisualizer3D& setViewportSize(const Vector2& size); - - /** - * @brief Set base object color - * @return Reference to self (for method chaining) - * - * Initial value is @cpp 0xffffffff_rgbaf @ce. Expects that either - * @ref Flag::Wireframe or @ref Flag::InstancedObjectId / - * @ref Flag::PrimitiveId is enabled. In case of the latter, the color - * is multiplied with the color map coming from - * @ref bindColorMapTexture(). - */ - MeshVisualizer3D& setColor(const Color4& color) { - return static_cast(Implementation::MeshVisualizerBase::setColor(color)); - } - - /** - * @brief Set wireframe color - * @return Reference to self (for method chaining) - * - * Initial value is @cpp 0x000000ff_rgbaf @ce. Expects that - * @ref Flag::Wireframe is enabled. - */ - MeshVisualizer3D& setWireframeColor(const Color4& color) { - return static_cast(Implementation::MeshVisualizerBase::setWireframeColor(color)); - } - - /** - * @brief Set wireframe width - * @return Reference to self (for method chaining) - * - * Value is in screen space (depending on @ref setViewportSize()), - * initial value is @cpp 1.0f @ce. Expects that @ref Flag::Wireframe is - * enabled. - */ - MeshVisualizer3D& setWireframeWidth(Float width) { - return static_cast(Implementation::MeshVisualizerBase::setWireframeWidth(width)); - } - - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief Set color map transformation - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * Offset and scale applied to the input value coming either from the - * @ref ObjectId attribute or @glsl gl_PrimitiveID @ce, resulting value - * is then used to fetch a color from a color map bound with - * @ref bindColorMapTexture(). Initial value is @cpp 1.0f/512.0f @ce - * and @cpp 1.0/256.0f @ce, meaning that for a 256-entry colormap the - * first 256 values get an exact color from it and the next values will - * be either clamped to last color or repeated depending on the color - * map texture wrapping mode. Expects that either - * @ref Flag::InstancedObjectId or @ref Flag::PrimitiveId / - * @ref Flag::PrimitiveIdFromVertexId is enabled. - * - * Note that this shader doesn't directly offer a - * @ref Flat::setObjectId() "setObjectId()" uniform that's used to - * offset the per-vertex / per-instance ID. Instead, you need to encode - * the base offset into the @p offset parameter. - * @requires_gles30 Object ID visualization requires integer attributes - * while primitive ID visualization requires the `gl_VertexID` / - * `gl_PrimitiveID` builtins, neither of which is available in - * OpenGL ES 2.0. - * @requires_webgl20 Object ID visualization requires integer - * attributes while primitive ID visualization requires at least - * the `gl_VertexID` builtin, neither of which is available in - * WebGL 1. - */ - MeshVisualizer3D& setColorMapTransformation(Float offset, Float scale) { - return static_cast(Implementation::MeshVisualizerBase::setColorMapTransformation(offset, scale)); - } - - /** - * @brief Bind a color map texture - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * See also @ref setColorMapTransformation(). Expects that either - * @ref Flag::InstancedObjectId or @ref Flag::PrimitiveId / - * @ref Flag::PrimitiveIdFromVertexId is enabled. - * @requires_gles30 Object ID visualization requires integer attributes - * while primitive ID visualization requires the `gl_VertexID` / - * `gl_PrimitiveID` builtins, neither of which is available in - * OpenGL ES 2.0. - * @requires_webgl20 Object ID visualization requires integer - * attributes while primitive ID visualization requires at least - * the `gl_VertexID` builtin, neither of which is available in - * WebGL 1. - */ - MeshVisualizer3D& bindColorMapTexture(GL::Texture2D& texture) { - return static_cast(Implementation::MeshVisualizerBase::bindColorMapTexture(texture)); - } - #endif - - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - /** - * @brief Set line width - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * Value is in screen space (depending on @ref setViewportSize()), - * initial value is @cpp 1.0f @ce. Expects that - * @ref Flag::TangentDirection, - * @ref Flag::BitangentFromTangentDirection, - * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is - * enabled. - * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} - * @requires_gles30 Not defined in OpenGL ES 2.0. - * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / - * @gl_extension{EXT,geometry_shader} - * @requires_gles Geometry shaders are not available in WebGL. - */ - MeshVisualizer3D& setLineWidth(Float width); - - /** - * @brief Set line length - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * Value is in object space, initial value is @cpp 1.0f @ce. Expects - * that @ref Flag::TangentDirection, - * @ref Flag::BitangentFromTangentDirection, - * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is - * enabled. - * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} - * @requires_gles30 Not defined in OpenGL ES 2.0. - * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / - * @gl_extension{EXT,geometry_shader} - * @requires_gles Geometry shaders are not available in WebGL. - */ - MeshVisualizer3D& setLineLength(Float length); - #endif - - /** - * @brief Set line smoothness - * @return Reference to self (for method chaining) - * - * Value is in screen space (depending on @ref setViewportSize()), - * initial value is @cpp 2.0f @ce. Expects that @ref Flag::Wireframe, - * @ref Flag::TangentDirection, - * @ref Flag::BitangentFromTangentDirection, - * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is - * enabled. - */ - MeshVisualizer3D& setSmoothness(Float smoothness); - - private: - Int _transformationMatrixUniform{0}, - _projectionMatrixUniform{7}; - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - Int _normalMatrixUniform{8}, - _lineWidthUniform{9}, - _lineLengthUniform{10}; - #endif -}; +#include "Magnum/configure.h" #ifdef MAGNUM_BUILD_DEPRECATED -/** -@brief 3D mesh visualizer shader -@m_deprecated_since{2020,06} Use @ref MeshVisualizer3D instead. -*/ -typedef CORRADE_DEPRECATED("use MeshVisualizer3D instead") MeshVisualizer3D MeshVisualizer; -#endif +#include -/** @debugoperatorclassenum{MeshVisualizer2D,MeshVisualizer2D::Flag} */ -MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizer2D::Flag value); +#include "Magnum/Shaders/MeshVisualizerGL.h" -/** @debugoperatorclassenum{MeshVisualizer3D,MeshVisualizer3D::Flag} */ -MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizer3D::Flag value); +CORRADE_DEPRECATED_FILE("use Magnum/Shaders/MeshVisualizerGL.h and the MeshVisualizerGL2D / MeshVisualizer3D class instead") + +namespace Magnum { namespace Shaders { -/** @debugoperatorclassenum{MeshVisualizer2D,MeshVisualizer2D::Flags} */ -MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizer2D::Flags value); +/** @brief @copybrief MeshVisualizerGL2D + * @m_deprecated_since_latest Use @ref MeshVisualizerGL2D instead. + */ +typedef CORRADE_DEPRECATED("use MeshVisualizerGL2D instead") MeshVisualizerGL2D MeshVisualizer2D; -/** @debugoperatorclassenum{MeshVisualizer3D,MeshVisualizer3D::Flags} */ -MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizer3D::Flags value); +/** @brief @copybrief MeshVisualizerGL3D + * @m_deprecated_since_latest Use @ref MeshVisualizerGL3D instead. + */ +typedef CORRADE_DEPRECATED("use MeshVisualizerGL3D instead") MeshVisualizerGL3D MeshVisualizer3D; -CORRADE_ENUMSET_OPERATORS(MeshVisualizer2D::Flags) -CORRADE_ENUMSET_OPERATORS(MeshVisualizer3D::Flags) +/** @brief @copybrief MeshVisualizerGL3D + * @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D instead. + */ +typedef CORRADE_DEPRECATED("use MeshVisualizerGL3D instead") MeshVisualizerGL3D MeshVisualizer; }} +#else +#error use Magnum/Shaders/MeshVisualizerGL.h and the MeshVisualizerGL2D / MeshVisualizer3D class instead +#endif #endif diff --git a/src/Magnum/Shaders/MeshVisualizer.cpp b/src/Magnum/Shaders/MeshVisualizerGL.cpp similarity index 83% rename from src/Magnum/Shaders/MeshVisualizer.cpp rename to src/Magnum/Shaders/MeshVisualizerGL.cpp index f02e055bf..2319626f5 100644 --- a/src/Magnum/Shaders/MeshVisualizer.cpp +++ b/src/Magnum/Shaders/MeshVisualizerGL.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "MeshVisualizer.h" +#include "MeshVisualizerGL.h" #include #include @@ -52,7 +52,7 @@ namespace { namespace Implementation { -MeshVisualizerBase::MeshVisualizerBase(FlagsBase flags): _flags{flags} { +MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags): _flags{flags} { #ifndef MAGNUM_TARGET_GLES2 #ifndef CORRADE_NO_ASSERT Int countMutuallyExclusive = 0; @@ -61,7 +61,7 @@ MeshVisualizerBase::MeshVisualizerBase(FlagsBase flags): _flags{flags} { if(flags & FlagBase::PrimitiveIdFromVertexId) ++countMutuallyExclusive; #endif CORRADE_ASSERT(countMutuallyExclusive <= 1, - "Shaders::MeshVisualizer: Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive", ); + "Shaders::MeshVisualizerGL: Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive", ); #endif #ifndef MAGNUM_TARGET_GLES2 @@ -90,12 +90,12 @@ MeshVisualizerBase::MeshVisualizerBase(FlagsBase flags): _flags{flags} { #ifdef MAGNUM_BUILD_STATIC /* Import resources on static build, if not already */ - if(!Utility::Resource::hasGroup("MagnumShaders")) + if(!Utility::Resource::hasGroup("MagnumShadersGL")) importShaderResources(); #endif } -GL::Version MeshVisualizerBase::setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const { +GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const { #ifndef MAGNUM_TARGET_GLES const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); /* Extended in MeshVisualizer3D for TBN visualization */ @@ -138,43 +138,43 @@ GL::Version MeshVisualizerBase::setupShaders(GL::Shader& vert, GL::Shader& frag, return version; } -MeshVisualizerBase& MeshVisualizerBase::setColor(const Color4& color) { +MeshVisualizerGLBase& MeshVisualizerGLBase::setColor(const Color4& color) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(_flags & (FlagBase::Wireframe|FlagBase::InstancedObjectId|FlagBase::VertexId|FlagBase::PrimitiveId), - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled", *this); + "Shaders::MeshVisualizerGL::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled", *this); #else CORRADE_ASSERT(_flags & FlagBase::Wireframe, - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe enabled", *this); + "Shaders::MeshVisualizerGL::setColor(): the shader was not created with wireframe enabled", *this); #endif setUniform(_colorUniform, color); return *this; } -MeshVisualizerBase& MeshVisualizerBase::setWireframeColor(const Color4& color) { +MeshVisualizerGLBase& MeshVisualizerGLBase::setWireframeColor(const Color4& color) { CORRADE_ASSERT(_flags & FlagBase::Wireframe, - "Shaders::MeshVisualizer::setWireframeColor(): the shader was not created with wireframe enabled", *this); + "Shaders::MeshVisualizerGL::setWireframeColor(): the shader was not created with wireframe enabled", *this); setUniform(_wireframeColorUniform, color); return *this; } -MeshVisualizerBase& MeshVisualizerBase::setWireframeWidth(const Float width) { +MeshVisualizerGLBase& MeshVisualizerGLBase::setWireframeWidth(const Float width) { CORRADE_ASSERT(_flags & FlagBase::Wireframe, - "Shaders::MeshVisualizer::setWireframeWidth(): the shader was not created with wireframe enabled", *this); + "Shaders::MeshVisualizerGL::setWireframeWidth(): the shader was not created with wireframe enabled", *this); setUniform(_wireframeWidthUniform, width); return *this; } #ifndef MAGNUM_TARGET_GLES2 -MeshVisualizerBase& MeshVisualizerBase::setColorMapTransformation(const Float offset, const Float scale) { +MeshVisualizerGLBase& MeshVisualizerGLBase::setColorMapTransformation(const Float offset, const Float scale) { CORRADE_ASSERT(_flags & (FlagBase::InstancedObjectId|FlagBase::VertexId|FlagBase::PrimitiveId), - "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled", *this); + "Shaders::MeshVisualizerGL::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled", *this); setUniform(_colorMapOffsetScaleUniform, Vector2{offset, scale}); return *this; } -MeshVisualizerBase& MeshVisualizerBase::bindColorMapTexture(GL::Texture2D& texture) { +MeshVisualizerGLBase& MeshVisualizerGLBase::bindColorMapTexture(GL::Texture2D& texture) { CORRADE_ASSERT(_flags & (FlagBase::InstancedObjectId|FlagBase::VertexId|FlagBase::PrimitiveId), - "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled", *this); + "Shaders::MeshVisualizerGL::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled", *this); texture.bind(ColorMapTextureUnit); return *this; } @@ -182,16 +182,16 @@ MeshVisualizerBase& MeshVisualizerBase::bindColorMapTexture(GL::Texture2D& textu } -MeshVisualizer2D::MeshVisualizer2D(const Flags flags): Implementation::MeshVisualizerBase{Implementation::MeshVisualizerBase::FlagBase(UnsignedShort(flags))} { +MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): Implementation::MeshVisualizerGLBase{Implementation::MeshVisualizerGLBase::FlagBase(UnsignedShort(flags))} { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizer2D: at least one visualization feature has to be enabled", ); + "Shaders::MeshVisualizerGL2D: at least one visualization feature has to be enabled", ); #else CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizer2D: at least Flag::Wireframe has to be enabled", ); + "Shaders::MeshVisualizerGL2D: at least Flag::Wireframe has to be enabled", ); #endif - Utility::Resource rs{"MagnumShaders"}; + Utility::Resource rs{"MagnumShadersGL"}; GL::Shader vert{NoCreate}; GL::Shader frag{NoCreate}; const GL::Version version = setupShaders(vert, frag, rs); @@ -314,7 +314,7 @@ MeshVisualizer2D::MeshVisualizer2D(const Flags flags): Implementation::MeshVisua #endif } -MeshVisualizer2D& MeshVisualizer2D::setViewportSize(const Vector2& size) { +MeshVisualizerGL2D& MeshVisualizerGL2D::setViewportSize(const Vector2& size) { /* Not asserting here, since the relation to wireframe is a bit vague. Also it's an ugly hack that should be removed, ideally. */ if(flags() & Flag::Wireframe && !(flags() & Flag::NoGeometryShader)) @@ -322,37 +322,37 @@ MeshVisualizer2D& MeshVisualizer2D::setViewportSize(const Vector2& size) { return *this; } -MeshVisualizer2D& MeshVisualizer2D::setTransformationProjectionMatrix(const Matrix3& matrix) { +MeshVisualizerGL2D& MeshVisualizerGL2D::setTransformationProjectionMatrix(const Matrix3& matrix) { setUniform(_transformationProjectionMatrixUniform, matrix); return *this; } -MeshVisualizer2D& MeshVisualizer2D::setSmoothness(const Float smoothness) { +MeshVisualizerGL2D& MeshVisualizerGL2D::setSmoothness(const Float smoothness) { /* This is a bit vaguely related but less vague than setViewportSize() so asserting in this case. */ CORRADE_ASSERT(flags() & Flag::Wireframe, - "Shaders::MeshVisualizer2D::setSmoothness(): the shader was not created with wireframe enabled", *this); + "Shaders::MeshVisualizerGL2D::setSmoothness(): the shader was not created with wireframe enabled", *this); setUniform(_smoothnessUniform, smoothness); return *this; } -MeshVisualizer3D::MeshVisualizer3D(const Flags flags): Implementation::MeshVisualizerBase{Implementation::MeshVisualizerBase::FlagBase(UnsignedShort(flags))} { +MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): Implementation::MeshVisualizerGLBase{Implementation::MeshVisualizerGLBase::FlagBase(UnsignedShort(flags))} { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection|Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizer3D: at least one visualization feature has to be enabled", ); + "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", ); CORRADE_ASSERT(!(flags & Flag::NoGeometryShader && flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)), - "Shaders::MeshVisualizer3D: geometry shader has to be enabled when rendering TBN direction", ); + "Shaders::MeshVisualizerGL3D: geometry shader has to be enabled when rendering TBN direction", ); CORRADE_ASSERT(!(flags & Flag::BitangentDirection && flags & Flag::BitangentFromTangentDirection), - "Shaders::MeshVisualizer3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive", ); + "Shaders::MeshVisualizerGL3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive", ); #elif !defined(MAGNUM_TARGET_GLES2) CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::InstancedObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizer3D: at least one visualization feature has to be enabled", ); + "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", ); #else CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), - "Shaders::MeshVisualizer3D: at least Flag::Wireframe has to be enabled", ); + "Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", ); #endif - Utility::Resource rs{"MagnumShaders"}; + Utility::Resource rs{"MagnumShadersGL"}; GL::Shader vert{NoCreate}; GL::Shader frag{NoCreate}; const GL::Version version = setupShaders(vert, frag, rs); @@ -547,26 +547,26 @@ MeshVisualizer3D::MeshVisualizer3D(const Flags flags): Implementation::MeshVisua #endif } -MeshVisualizer3D& MeshVisualizer3D::setTransformationMatrix(const Matrix4& matrix) { +MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) { setUniform(_transformationMatrixUniform, matrix); return *this; } -MeshVisualizer3D& MeshVisualizer3D::setProjectionMatrix(const Matrix4& matrix) { +MeshVisualizerGL3D& MeshVisualizerGL3D::setProjectionMatrix(const Matrix4& matrix) { setUniform(_projectionMatrixUniform, matrix); return *this; } #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -MeshVisualizer3D& MeshVisualizer3D::setNormalMatrix(const Matrix3x3& matrix) { +MeshVisualizerGL3D& MeshVisualizerGL3D::setNormalMatrix(const Matrix3x3& matrix) { CORRADE_ASSERT(flags() & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection), - "Shaders::MeshVisualizer3D::setNormalMatrix(): the shader was not created with TBN direction enabled", *this); + "Shaders::MeshVisualizerGL3D::setNormalMatrix(): the shader was not created with TBN direction enabled", *this); setUniform(_normalMatrixUniform, matrix); return *this; } #endif -MeshVisualizer3D& MeshVisualizer3D::setViewportSize(const Vector2& size) { +MeshVisualizerGL3D& MeshVisualizerGL3D::setViewportSize(const Vector2& size) { /* Not asserting here, since the relation to wireframe is a bit vague. Also it's an ugly hack that should be removed, ideally. */ if((flags() & Flag::Wireframe && !(flags() & Flag::NoGeometryShader)) @@ -579,22 +579,22 @@ MeshVisualizer3D& MeshVisualizer3D::setViewportSize(const Vector2& size) { } #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) -MeshVisualizer3D& MeshVisualizer3D::setLineWidth(const Float width) { +MeshVisualizerGL3D& MeshVisualizerGL3D::setLineWidth(const Float width) { CORRADE_ASSERT(flags() & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection), - "Shaders::MeshVisualizer3D::setLineWidth(): the shader was not created with TBN direction enabled", *this); + "Shaders::MeshVisualizerGL3D::setLineWidth(): the shader was not created with TBN direction enabled", *this); setUniform(_lineWidthUniform, width); return *this; } -MeshVisualizer3D& MeshVisualizer3D::setLineLength(const Float length) { +MeshVisualizerGL3D& MeshVisualizerGL3D::setLineLength(const Float length) { CORRADE_ASSERT(flags() & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection), - "Shaders::MeshVisualizer3D::setLineLength(): the shader was not created with TBN direction enabled", *this); + "Shaders::MeshVisualizerGL3D::setLineLength(): the shader was not created with TBN direction enabled", *this); setUniform(_lineLengthUniform, length); return *this; } #endif -MeshVisualizer3D& MeshVisualizer3D::setSmoothness(const Float smoothness) { +MeshVisualizerGL3D& MeshVisualizerGL3D::setSmoothness(const Float smoothness) { #ifndef CORRADE_NO_ASSERT /* This is a bit vaguely related but less vague than setViewportSize() so asserting in this case. */ @@ -604,18 +604,18 @@ MeshVisualizer3D& MeshVisualizer3D::setSmoothness(const Float smoothness) { constexpr Flags allowed = Flag::Wireframe; #endif CORRADE_ASSERT(flags() & allowed, - "Shaders::MeshVisualizer3D::setSmoothness(): the shader was not created with wireframe or TBN direction enabled", *this); + "Shaders::MeshVisualizerGL3D::setSmoothness(): the shader was not created with wireframe or TBN direction enabled", *this); #endif setUniform(_smoothnessUniform, smoothness); return *this; } -Debug& operator<<(Debug& debug, const MeshVisualizer2D::Flag value) { - debug << "Shaders::MeshVisualizer2D::Flag" << Debug::nospace; +Debug& operator<<(Debug& debug, const MeshVisualizerGL2D::Flag value) { + debug << "Shaders::MeshVisualizerGL2D::Flag" << Debug::nospace; switch(value) { /* LCOV_EXCL_START */ - #define _c(v) case MeshVisualizer2D::Flag::v: return debug << "::" #v; + #define _c(v) case MeshVisualizerGL2D::Flag::v: return debug << "::" #v; _c(NoGeometryShader) _c(Wireframe) #ifndef MAGNUM_TARGET_GLES2 @@ -633,12 +633,12 @@ Debug& operator<<(Debug& debug, const MeshVisualizer2D::Flag value) { return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } -Debug& operator<<(Debug& debug, const MeshVisualizer3D::Flag value) { - debug << "Shaders::MeshVisualizer3D::Flag" << Debug::nospace; +Debug& operator<<(Debug& debug, const MeshVisualizerGL3D::Flag value) { + debug << "Shaders::MeshVisualizerGL3D::Flag" << Debug::nospace; switch(value) { /* LCOV_EXCL_START */ - #define _c(v) case MeshVisualizer3D::Flag::v: return debug << "::" #v; + #define _c(v) case MeshVisualizerGL3D::Flag::v: return debug << "::" #v; _c(NoGeometryShader) _c(Wireframe) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -662,41 +662,41 @@ Debug& operator<<(Debug& debug, const MeshVisualizer3D::Flag value) { return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } -Debug& operator<<(Debug& debug, const MeshVisualizer2D::Flags value) { - return Containers::enumSetDebugOutput(debug, value, "Shaders::MeshVisualizer2D::Flags{}", { - MeshVisualizer2D::Flag::Wireframe, +Debug& operator<<(Debug& debug, const MeshVisualizerGL2D::Flags value) { + return Containers::enumSetDebugOutput(debug, value, "Shaders::MeshVisualizerGL2D::Flags{}", { + MeshVisualizerGL2D::Flag::Wireframe, /* Wireframe contains this on ES2 and WebGL 1 so it's not reported there */ - MeshVisualizer2D::Flag::NoGeometryShader, + MeshVisualizerGL2D::Flag::NoGeometryShader, #ifndef MAGNUM_TARGET_GLES2 - MeshVisualizer2D::Flag::InstancedObjectId, - MeshVisualizer2D::Flag::VertexId, - MeshVisualizer2D::Flag::PrimitiveIdFromVertexId, /* Superset of PrimitiveId */ + MeshVisualizerGL2D::Flag::InstancedObjectId, + MeshVisualizerGL2D::Flag::VertexId, + MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId, /* Superset of PrimitiveId */ #ifndef MAGNUM_TARGET_WEBGL - MeshVisualizer2D::Flag::PrimitiveId + MeshVisualizerGL2D::Flag::PrimitiveId #endif #endif }); } -Debug& operator<<(Debug& debug, const MeshVisualizer3D::Flags value) { - return Containers::enumSetDebugOutput(debug, value, "Shaders::MeshVisualizer3D::Flags{}", { - MeshVisualizer3D::Flag::Wireframe, +Debug& operator<<(Debug& debug, const MeshVisualizerGL3D::Flags value) { + return Containers::enumSetDebugOutput(debug, value, "Shaders::MeshVisualizerGL3D::Flags{}", { + MeshVisualizerGL3D::Flag::Wireframe, /* Wireframe contains this on ES2 and WebGL 1 so it's not reported there */ - MeshVisualizer3D::Flag::NoGeometryShader, + MeshVisualizerGL3D::Flag::NoGeometryShader, #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - MeshVisualizer3D::Flag::TangentDirection, - MeshVisualizer3D::Flag::BitangentFromTangentDirection, - MeshVisualizer3D::Flag::BitangentDirection, - MeshVisualizer3D::Flag::NormalDirection, + MeshVisualizerGL3D::Flag::TangentDirection, + MeshVisualizerGL3D::Flag::BitangentFromTangentDirection, + MeshVisualizerGL3D::Flag::BitangentDirection, + MeshVisualizerGL3D::Flag::NormalDirection, #endif #ifndef MAGNUM_TARGET_GLES2 - MeshVisualizer3D::Flag::InstancedObjectId, - MeshVisualizer3D::Flag::VertexId, - MeshVisualizer3D::Flag::PrimitiveIdFromVertexId, /* Superset of PrimitiveId */ + MeshVisualizerGL3D::Flag::InstancedObjectId, + MeshVisualizerGL3D::Flag::VertexId, + MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId, /* Superset of PrimitiveId */ #ifndef MAGNUM_TARGET_WEBGL - MeshVisualizer3D::Flag::PrimitiveId + MeshVisualizerGL3D::Flag::PrimitiveId #endif #endif }); diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h new file mode 100644 index 000000000..c0997486e --- /dev/null +++ b/src/Magnum/Shaders/MeshVisualizerGL.h @@ -0,0 +1,1038 @@ +#ifndef Magnum_Shaders_MeshVisualizerGL_h +#define Magnum_Shaders_MeshVisualizerGL_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Shaders::MeshVisualizerGL2D, @ref Magnum::Shaders::MeshVisualizerGL3D + * @m_since_latest + */ + +#include + +#include "Magnum/DimensionTraits.h" +#include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/Shaders/GenericGL.h" +#include "Magnum/Shaders/visibility.h" + +namespace Magnum { namespace Shaders { + +namespace Implementation { + +class MAGNUM_SHADERS_EXPORT MeshVisualizerGLBase: public GL::AbstractShaderProgram { + protected: + enum class FlagBase: UnsignedShort { + /* Unlike the public Wireframe flag, this one doesn't include + NoGeometryShader on ES2 as that would make the checks too + complex */ + Wireframe = 1 << 0, + NoGeometryShader = 1 << 1, + #ifndef MAGNUM_TARGET_GLES2 + InstancedObjectId = 1 << 2, + VertexId = 1 << 3, + PrimitiveId = 1 << 4, + PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId + #endif + }; + typedef Containers::EnumSet FlagsBase; + + CORRADE_ENUMSET_FRIEND_OPERATORS(FlagsBase) + + explicit MeshVisualizerGLBase(FlagsBase flags); + explicit MeshVisualizerGLBase(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} + + MAGNUM_SHADERS_LOCAL GL::Version setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const; + + MeshVisualizerGLBase& setColor(const Color4& color); + MeshVisualizerGLBase& setWireframeColor(const Color4& color); + MeshVisualizerGLBase& setWireframeWidth(Float width); + #ifndef MAGNUM_TARGET_GLES2 + MeshVisualizerGLBase& setColorMapTransformation(Float offset, Float scale); + MeshVisualizerGLBase& bindColorMapTexture(GL::Texture2D& texture); + #endif + + /* Prevent accidentally calling irrelevant functions */ + #ifndef MAGNUM_TARGET_GLES + using GL::AbstractShaderProgram::drawTransformFeedback; + #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + using GL::AbstractShaderProgram::dispatchCompute; + #endif + + FlagsBase _flags; + Int _colorUniform{1}, + _wireframeColorUniform{2}, + _wireframeWidthUniform{3}, + _smoothnessUniform{4}, + _viewportSizeUniform{5}; + #ifndef MAGNUM_TARGET_GLES2 + Int _colorMapOffsetScaleUniform{6}; + #endif +}; + +} + +/** +@brief 2D mesh visualization OpenGL shader +@m_since_latest + +Visualizes wireframe, per-vertex/per-instance object ID or primitive ID of 2D +meshes. You need to provide the @ref Position attribute in your triangle mesh. +Use @ref setTransformationProjectionMatrix(), @ref setColor() and others to +configure the shader. + +@m_class{m-row} + +@parblock + +@m_div{m-col-m-4 m-col-t-6 m-push-m-2 m-nopadt m-nopadx} +@image html shaders-meshvisualizer2d.png width=256px +@m_enddiv + +@m_div{m-col-m-4 m-col-t-6 m-push-m-2 m-nopadt m-nopadx} +@image html shaders-meshvisualizer2d-primitiveid.png width=256px +@m_enddiv + +@endparblock + +The shader expects that you enable wireframe visualization by passing an +appropriate @ref Flag to the constructor --- there's no default behavior with +nothing enabled. The shader is a 2D variant of @ref MeshVisualizerGL3D with +mostly identical workflow. See its documentation for more information. +*/ +class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisualizerGLBase { + public: + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector2 "Vector2". + */ + typedef typename GenericGL2D::Position Position; + + /** + * @brief Vertex index + * + * See @ref MeshVisualizerGL3D::VertexIndex for more information. + */ + typedef GL::Attribute<4, Float> VertexIndex; + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief (Instanced) object ID + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. + * Used only if @ref Flag::InstancedObjectId is set. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. + */ + typedef GenericGL3D::ObjectId ObjectId; + #endif + + enum: UnsignedInt { + /** + * Color shader output. @ref shaders-generic "Generic output", + * present always. Expects three- or four-component floating-point + * or normalized buffer attachment. + */ + ColorOutput = GenericGL2D::ColorOutput + }; + + /** + * @brief Flag + * + * @see @ref Flags, @ref MeshVisualizerGL2D() + */ + enum class Flag: UnsignedShort { + /** + * Visualize wireframe. On OpenGL ES 2.0 and WebGL this also + * enables @ref Flag::NoGeometryShader. + */ + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + Wireframe = 1 << 0, + #else + Wireframe = (1 << 0) | (1 << 1), + #endif + + /** + * Don't use a geometry shader for wireframe visualization. If + * enabled, you might need to provide also the @ref VertexIndex + * attribute in the mesh. On OpenGL ES 2.0 and WebGL enabled + * alongside @ref Flag::Wireframe. + */ + NoGeometryShader = 1 << 1, + + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc MeshVisualizerGL3D::Flag::InstancedObjectId */ + InstancedObjectId = 1 << 2, + + /** @copydoc MeshVisualizerGL3D::Flag::VertexId */ + VertexId = 1 << 3, + + #ifndef MAGNUM_TARGET_WEBGL + /** @copydoc MeshVisualizerGL3D::Flag::PrimitiveId */ + PrimitiveId = 1 << 4, + #endif + + /** @copydoc MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId */ + #ifndef MAGNUM_TARGET_WEBGL + PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId + #else + PrimitiveIdFromVertexId = (1 << 5)|(1 << 4) + #endif + #endif + }; + + /** @brief Flags */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param flags Flags + * + * At least @ref Flag::Wireframe is expected to be enabled. + */ + explicit MeshVisualizerGL2D(Flags flags); + + /** + * @brief Construct without creating the underlying OpenGL object + * + * The constructed instance is equivalent to a moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit MeshVisualizerGL2D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {} + + /** @brief Copying is not allowed */ + MeshVisualizerGL2D(const MeshVisualizerGL2D&) = delete; + + /** @brief Move constructor */ + MeshVisualizerGL2D(MeshVisualizerGL2D&&) noexcept = default; + + /** @brief Copying is not allowed */ + MeshVisualizerGL2D& operator=(const MeshVisualizerGL2D&) = delete; + + /** @brief Move assignment */ + MeshVisualizerGL2D& operator=(MeshVisualizerGL2D&&) noexcept = default; + + /** @brief Flags */ + Flags flags() const { + return Flag(UnsignedShort(Implementation::MeshVisualizerGLBase::_flags)); + } + + /** + * @brief Set transformation and projection matrix + * @return Reference to self (for method chaining) + * + * Initial value is an identity matrix. + */ + MeshVisualizerGL2D& setTransformationProjectionMatrix(const Matrix3& matrix); + + /** + * @brief Set viewport size + * @return Reference to self (for method chaining) + * + * Has effect only if @ref Flag::Wireframe is enabled and geometry + * shaders are used, otherwise it does nothing. Initial value is a zero + * vector. + */ + MeshVisualizerGL2D& setViewportSize(const Vector2& size); + + /** + * @brief Set base object color + * @return Reference to self (for method chaining) + * + * Initial value is @cpp 0xffffffff_rgbaf @ce. Expects that either + * @ref Flag::Wireframe or @ref Flag::InstancedObjectId / + * @ref Flag::PrimitiveId is enabled. In case of the latter, the color + * is multiplied with the color map coming from + * @ref bindColorMapTexture(). + */ + MeshVisualizerGL2D& setColor(const Color4& color) { + return static_cast(Implementation::MeshVisualizerGLBase::setColor(color)); + } + + /** + * @brief Set wireframe color + * @return Reference to self (for method chaining) + * + * Initial value is @cpp 0x000000ff_rgbaf @ce. Expects that + * @ref Flag::Wireframe is enabled. + */ + MeshVisualizerGL2D& setWireframeColor(const Color4& color) { + return static_cast(Implementation::MeshVisualizerGLBase::setWireframeColor(color)); + } + + /** + * @brief Set wireframe width + * @return Reference to self (for method chaining) + * + * Value is in screen space (depending on @ref setViewportSize()), + * initial value is @cpp 1.0f @ce. Expects that @ref Flag::Wireframe is + * enabled. + */ + MeshVisualizerGL2D& setWireframeWidth(Float width) { + return static_cast(Implementation::MeshVisualizerGLBase::setWireframeWidth(width)); + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc MeshVisualizerGL3D::setColorMapTransformation() */ + MeshVisualizerGL2D& setColorMapTransformation(Float offset, Float scale) { + return static_cast(Implementation::MeshVisualizerGLBase::setColorMapTransformation(offset, scale)); + } + + /** @copydoc MeshVisualizerGL3D::bindColorMapTexture() */ + MeshVisualizerGL2D& bindColorMapTexture(GL::Texture2D& texture) { + return static_cast(Implementation::MeshVisualizerGLBase::bindColorMapTexture(texture)); + } + #endif + + /** + * @brief Set line smoothness + * @return Reference to self (for method chaining) + * + * Value is in screen space (depending on @ref setViewportSize()), + * initial value is @cpp 2.0f @ce. Expects that @ref Flag::Wireframe is + * enabled. + */ + MeshVisualizerGL2D& setSmoothness(Float smoothness); + + private: + Int _transformationProjectionMatrixUniform{0}; +}; + +/** +@brief 3D mesh visualization OpenGL shader +@m_since_latest + +Visualizes wireframe, per-vertex/per-instance object ID, primitive ID or +tangent space of 3D meshes. You need to provide the @ref Position attribute in +your triangle mesh at the very least. Use @ref setTransformationProjectionMatrix(), +@ref setColor() and others to configure the shader. + +@m_class{m-row} + +@parblock + +@m_div{m-col-m-4 m-col-t-6 m-push-m-2 m-text-center m-nopadt m-nopadx} +@image html shaders-meshvisualizer3d.png width=256px +@ref Shaders-MeshVisualizerGL3D-wireframe, \n +@ref Shaders-MeshVisualizerGL3D-tbn +@m_enddiv + +@m_div{m-col-m-4 m-col-t-6 m-push-m-2 m-text-center m-nopadt m-nopadx} +@image html shaders-meshvisualizer3d-primitiveid.png width=256px +@ref Shaders-MeshVisualizerGL3D-object-id +@m_enddiv + +@endparblock + +The shader expects that you enable wireframe visualization, tangent space +visualization or object/primitive ID visualization by passing an appropriate +@ref Flag to the constructor --- there's no default behavior with nothing +enabled. + +@section Shaders-MeshVisualizerGL3D-wireframe Wireframe visualization + +Wireframe visualization is done by enabling @ref Flag::Wireframe. It is done +either using geometry shaders or with help of additional vertex information. If +you have geometry shaders available, you don't need to do anything else except +calling @ref setViewportSize() to correctly size the wireframe --- without +this, the mesh will be rendered in a single color. + +@requires_gl32 Extension @gl_extension{ARB,geometry_shader4} for wireframe + rendering using geometry shaders. +@requires_es_extension Extension @gl_extension{EXT,geometry_shader} for + wireframe rendering using geometry shaders. + +If you don't have geometry shaders, you need to enable @ref Flag::NoGeometryShader +(done by default in OpenGL ES 2.0) and use only **non-indexed** triangle meshes +(see @ref MeshTools::duplicate() for a possible solution). Additionaly, if you +have OpenGL < 3.1 or OpenGL ES 2.0, you need to provide also the +@ref VertexIndex attribute. + +@requires_gles30 Extension @gl_extension{OES,standard_derivatives} for + wireframe rendering without geometry shaders. + +If using geometry shaders on OpenGL ES, @gl_extension{NV,shader_noperspective_interpolation} +is optionally used for improving line appearance. On desktop OpenGL this is +done implicitly. + +If you want to render just the wireframe on top of an existing mesh, call +@ref setColor() with @cpp 0x00000000_rgbaf @ce. Alpha / transparency is +supported by the shader implicitly, but to have it working on the framebuffer, +you need to enable @ref GL::Renderer::Feature::Blending and set up the blending +function. See @ref GL::Renderer::setBlendFunction() for details. + +@subsection Shaders-MeshVisualizerGL3D-wireframe-geom Example setup with a geometry shader (desktop GL, OpenGL ES 3.2) + +Common mesh setup: + +@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-geom1 + +Common rendering setup: + +@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-geom2 + +@subsection Shaders-MeshVisualizerGL3D-wireframe-no-geom Example setup for indexed meshes without a geometry shader + +The vertices have to be converted to a non-indexed array first. Mesh setup: + +@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-no-geom1 + +Rendering setup: + +@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-no-geom2 + +@subsection Shaders-MeshVisualizerGL3D-usage-wireframe-no-geom-old Wireframe visualization of non-indexed meshes without a geometry shader on older hardware + +You need to provide also the @ref VertexIndex attribute. Mesh setup *in +addition to the above*: + +@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-no-geom-old + +Rendering setup the same as above. + +@section Shaders-MeshVisualizerGL3D-tbn Tangent space visualization + +On platforms with geometry shaders (desktop GL, OpenGL ES 3.2), the shader is +able to visualize tangents, bitangent and normal direction via colored lines +coming out of vertices (red, green and blue for tangent, bitangent and normal, respectively). This can be enabled together with wireframe visualization, +however note that when both are enabled, the lines are not antialiased to avoid +depth ordering artifacts. + +For tangents and normals, you need to provide the @ref Tangent and @ref Normal +attributes and enable @ref Flag::TangentDirection and +@ref Flag::NormalDirection, respectively. If any of the attributes isn't +present, its data are implicitly zero and thus the direction isn't shown --- +which means you don't need to worry about having two active variants of the +shader and switching between either depending on whether tangents are present +or not. + +For bitangents however, there are two possible representations --- the more +efficient one is via a fourth component in the tangent attribute that +indicates tangent space handedness, in which case you'll be using the +@ref Tangent4 attribute instead of @ref Tangent, and enable +@ref Flag::BitangentFromTangentDirection. The other, more obvious but less +efficient representation, is a dedicated @ref Bitangent attribute (in which +case you'll enable @ref Flag::BitangentDirection). Note that these two are +mutually exclusive, so you need to choose either of them based on what given +mesh contains. Example for the first case: + +@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-tbn1 + +Rendering setup: + +@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-tbn2 + +@section Shaders-MeshVisualizerGL3D-object-id Object, vertex and primitive ID visualization + +If the mesh contains a per-vertex (or instanced) @ref ObjectId, it can be +visualized by enabling @ref Flag::InstancedObjectId. For the actual +visualization you need to provide a color map using @ref bindColorMapTexture() +and use @ref setColorMapTransformation() to map given range of discrete IDs to +the @f$ [0, 1] @f$ texture range. Various colormap presets are in the +@ref DebugTools::ColorMap namespace. Example usage: + +@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-usage-object-id + +If you enable @ref Flag::VertexId, the shader will use the color map to +visualize how are vertices shared among primitives. That's useful for +inspecting mesh connectivity --- primitives sharing vertices will have a smooth +color map transition while duplicated vertices will cause a sharp edge. This +relies on the @glsl gl_VertexID @ce GLSL builtin. + +The @ref Flag::PrimitiveId then visualizes the order in which primitives are +drawn. That's useful for example to see to see how well is the mesh optimized +for a post-transform vertex cache. This by default relies on the @glsl gl_PrimitiveID @ce GLSL builtin; with @ref Flag::PrimitiveIdFromVertexId it's +emulated using @glsl gl_VertexID @ce, expecting you to draw a non-indexed +triangle mesh. You can use @ref MeshTools::duplicate() (and potentially +@ref MeshTools::generateIndices()) to conveniently convert the mesh to a +non-indexed @ref MeshPrimitive::Triangles. + +@requires_gl32 The `gl_PrimitiveID` shader variable is not available on OpenGL + 3.1 and lower. +@requires_gl30 The `gl_VertexID` shader variable is not available on OpenGL + 2.1. +@requires_gles32 The `gl_PrimitiveID` shader variable is not available on + OpenGL ES 3.1 and lower. +@requires_gles30 The `gl_VertexID` shader variable is not available on OpenGL + ES 2.0. +@requires_gles `gl_PrimitiveID` is not available in WebGL. +@requires_webgl20 `gl_VertexID` is not available in WebGL 1.0. + +@see @ref shaders, @ref MeshVisualizerGL2D +@todo Understand and add support wireframe width/smoothness without GS +*/ +class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisualizerGLBase { + public: + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector3 "Vector3". + */ + typedef typename GenericGL3D::Position Position; + + /** + * @brief Tangent direction + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4 + * attribute. Used only if @ref Flag::TangentDirection is enabled. + */ + typedef typename GenericGL3D::Tangent Tangent; + + /** + * @brief Tangent direction with a bitangent sign + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector4 "Vector4". Use either this or the @ref Tangent + * attribute. Used only if @ref Flag::TangentDirection or + * @ref Flag::BitangentFromTangentDirection is enabled. + */ + typedef typename GenericGL3D::Tangent4 Tangent4; + + /** + * @brief Bitangent direction + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4 + * attribute. Used only if @ref Flag::BitangentDirection is enabled. + */ + typedef typename GenericGL3D::Bitangent Bitangent; + + /** + * @brief Normal direction + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector3 "Vector3". Used only if + * @ref Flag::NormalDirection is enabled. + */ + typedef typename GenericGL3D::Normal Normal; + + /** + * @brief Vertex index + * + * @ref Magnum::Float "Float", used only in OpenGL < 3.1 and OpenGL ES + * 2.0 if @ref Flag::Wireframe is enabled. This attribute (modulo 3) + * specifies index of given vertex in triangle, i.e. @cpp 0.0f @ce for + * first, @cpp 1.0f @ce for second, @cpp 2.0f @ce for third. In OpenGL + * 3.1, OpenGL ES 3.0 and newer this value is provided via the + * @cb{.glsl} gl_VertexID @ce shader builtin, so the attribute is not + * needed. + * + * @note This attribute uses the same slot as @ref GenericGL::ObjectId, + * but since Object ID is available only on ES3+ and vertex index + * is used only on ES2 contexts without @glsl gl_VertexID @ce, + * there should be no conflict between these two. + */ + typedef GL::Attribute<4, Float> VertexIndex; + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief (Instanced) object ID + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. + * Used only if @ref Flag::InstancedObjectId is set. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. + */ + typedef GenericGL3D::ObjectId ObjectId; + #endif + + enum: UnsignedInt { + /** + * Color shader output. @ref shaders-generic "Generic output", + * present always. Expects three- or four-component floating-point + * or normalized buffer attachment. + */ + ColorOutput = GenericGL3D::ColorOutput + }; + + /** + * @brief Flag + * + * @see @ref Flags, @ref MeshVisualizer() + */ + enum class Flag: UnsignedShort { + /** + * Visualize wireframe. On OpenGL ES 2.0 and WebGL this also + * enables @ref Flag::NoGeometryShader. + */ + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + Wireframe = 1 << 0, + #else + Wireframe = (1 << 0) | (1 << 1), + #endif + + /** + * Don't use a geometry shader for wireframe visualization. If + * enabled, you might need to provide also the @ref VertexIndex + * attribute in the mesh. On OpenGL ES 2.0 and WebGL enabled + * alongside @ref Flag::Wireframe. + * + * Mutually exclusive with @ref Flag::TangentDirection, + * @ref Flag::BitangentFromTangentDirection, + * @ref Flag::BitangentDirection and @ref Flag::NormalDirection --- + * those need a geometry shader always. + */ + NoGeometryShader = 1 << 1, + + #ifndef MAGNUM_TARGET_GLES2 + /** + * Visualize instanced object ID. You need to provide the + * @ref ObjectId attribute in the mesh. Mutually exclusive with + * @ref Flag::VertexId and @ref Flag::PrimitiveId. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL + * 1.0. + * @m_since{2020,06} + */ + InstancedObjectId = 1 << 2, + + /** + * Visualize vertex ID (@cpp gl_VertexID @ce). Useful for + * visualizing mesh connectivity --- primitives sharing vertices + * will have a smooth color map transition while duplicated + * vertices will cause a sharp edge. Mutually exclusive with + * @ref Flag::InstancedObjectId and @ref Flag::PrimitiveId. + * @requires_gl30 The `gl_VertexID` shader variable is not + * available on OpenGL 2.1. + * @requires_gles30 The `gl_VertexID` shader variable is not + * available on OpenGL ES 2.0. + * @requires_webgl20 `gl_VertexID` is not available in WebGL 1.0. + * @m_since{2020,06} + */ + VertexId = 1 << 3, + + #ifndef MAGNUM_TARGET_WEBGL + /** + * Visualize primitive ID (@cpp gl_PrimitiveID @ce). Useful for + * visualizing how well is the mesh optimized for a post-transform + * vertex cache. Mutually exclusive with + * @ref Flag::InstancedObjectId and @ref Flag::VertexId. See also + * @ref Flag::PrimitiveIdFromVertexId. + * @requires_gl32 The `gl_PrimitiveID` shader variable is not + * available on OpenGL 3.1 and lower. + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 The `gl_PrimitiveID` shader variable is not + * available on OpenGL ES 3.1 and lower. + * @requires_gles `gl_PrimitiveID` is not available in WebGL. + * @m_since{2020,06} + */ + PrimitiveId = 1 << 4, + #endif + + /** + * Visualize primitive ID on a non-indexed triangle mesh using + * @cpp gl_VertexID/3 @ce. Implicitly enables + * @ref Flag::PrimitiveId, mutually exclusive with + * @ref Flag::InstancedObjectId. Usable on OpenGL < 3.2, + * OpenGL ES < 3.2 and WebGL where @cpp gl_PrimitiveID @ce is not + * available. + * @requires_gl30 The `gl_VertexID` shader variable is not + * available on OpenGL 2.1. + * @requires_gles30 The `gl_VertexID` shader variable is not + * available on OpenGL ES 2.0. + * @requires_webgl20 `gl_VertexID` is not available in WebGL 1.0. + * @m_since{2020,06} + */ + #ifndef MAGNUM_TARGET_WEBGL + PrimitiveIdFromVertexId = (1 << 5)|PrimitiveId, + #else + PrimitiveIdFromVertexId = (1 << 5)|(1 << 4), + #endif + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /** + * Visualize tangent direction with red lines pointing out of + * vertices. You need to provide the @ref Tangent or @ref Tangent4 + * attribute in the mesh. Mutually exclusive with + * @ref Flag::NoGeometryShader (as this needs a geometry shader + * always). + * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / + * @gl_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + * @m_since{2020,06} + */ + TangentDirection = 1 << 6, + + /** + * Visualize bitangent direction with green lines pointing out of + * vertices. You need to provide both @ref Normal and @ref Tangent4 + * attributes in the mesh, alternatively you can provide the + * @ref Bitangent attribute and enable + * @ref Flag::BitangentDirection instead. Mutually exclusive with + * @ref Flag::NoGeometryShader (as this needs a geometry shader + * always). + * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / + * @gl_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + * @m_since{2020,06} + */ + BitangentFromTangentDirection = 1 << 7, + + /** + * Visualize bitangent direction with green lines pointing out of + * vertices. You need to provide the @ref Bitangent attribute in + * the mesh, alternatively you can provide both @ref Normal and + * @ref Tangent4 attributes and enable + * @ref Flag::BitangentFromTangentDirection instead. Mutually + * exclusive with @ref Flag::NoGeometryShader (as this needs a + * geometry shader always). + * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / + * @gl_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + * @m_since{2020,06} + */ + BitangentDirection = 1 << 8, + + /** + * Visualize normal direction with blue lines pointing out of + * vertices. You need to provide the @ref Normal attribute in the + * mesh. Mutually exclusive with @ref Flag::NoGeometryShader (as + * this needs a geometry shader always). + * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / + * @gl_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + * @m_since{2020,06} + */ + NormalDirection = 1 << 9 + #endif + }; + + /** @brief Flags */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param flags Flags + * + * At least @ref Flag::Wireframe or one of @ref Flag::TangentDirection, + * @ref Flag::BitangentFromTangentDirection, + * @ref Flag::BitangentDirection, @ref Flag::NormalDirection is + * expected to be enabled. + */ + explicit MeshVisualizerGL3D(Flags flags); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Constructor + * @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(Flags) + * instead. + */ + explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{{}} {} + #endif + + /** + * @brief Construct without creating the underlying OpenGL object + * + * The constructed instance is equivalent to a moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit MeshVisualizerGL3D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {} + + /** @brief Copying is not allowed */ + MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete; + + /** @brief Move constructor */ + MeshVisualizerGL3D(MeshVisualizerGL3D&&) noexcept = default; + + /** @brief Copying is not allowed */ + MeshVisualizerGL3D& operator=(const MeshVisualizerGL3D&) = delete; + + /** @brief Move assignment */ + MeshVisualizerGL3D& operator=(MeshVisualizerGL3D&&) noexcept = default; + + /** @brief Flags */ + Flags flags() const { + return Flag(UnsignedShort(Implementation::MeshVisualizerGLBase::_flags)); + } + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Set transformation and projection matrix + * @m_deprecated_since{2020,06} Use @ref setTransformationMatrix() and + * @ref setProjectionMatrix() instead. + */ + CORRADE_DEPRECATED("use setTransformationMatrix() and setProjectionMatrix() instead") MeshVisualizerGL3D& setTransformationProjectionMatrix(const Matrix4& matrix) { + /* Keep projection at identity, which should still work for + wireframe (but of course not for TBN visualization) */ + return setTransformationMatrix(matrix); + } + #endif + + /** + * @brief Set transformation matrix + * @return Reference to self (for method chaining) + * + * Initial value is an identity matrix. + */ + MeshVisualizerGL3D& setTransformationMatrix(const Matrix4& matrix); + + /** + * @brief Set projection matrix + * @return Reference to self (for method chaining) + * + * Initial value is an identity matrix. (i.e., an orthographic + * projection of the default @f$ [ -\boldsymbol{1} ; \boldsymbol{1} ] @f$ + * cube). + */ + MeshVisualizerGL3D& setProjectionMatrix(const Matrix4& matrix); + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /** + * @brief Set transformation matrix + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * Expects that @ref Flag::TangentDirection, + * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is + * enabled. The matrix doesn't need to be normalized, as + * renormalization is done per-fragment anyway. + * Initial value is an identity matrix. + * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / + * @gl_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + MeshVisualizerGL3D& setNormalMatrix(const Matrix3x3& matrix); + #endif + + /** + * @brief Set viewport size + * @return Reference to self (for method chaining) + * + * Has effect only if @ref Flag::Wireframe is enabled and geometry + * shaders are used; or if @ref Flag::TangentDirection, + * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is + * enabled, otherwise it does nothing. Initial value is a zero vector. + */ + MeshVisualizerGL3D& setViewportSize(const Vector2& size); + + /** + * @brief Set base object color + * @return Reference to self (for method chaining) + * + * Initial value is @cpp 0xffffffff_rgbaf @ce. Expects that either + * @ref Flag::Wireframe or @ref Flag::InstancedObjectId / + * @ref Flag::PrimitiveId is enabled. In case of the latter, the color + * is multiplied with the color map coming from + * @ref bindColorMapTexture(). + */ + MeshVisualizerGL3D& setColor(const Color4& color) { + return static_cast(Implementation::MeshVisualizerGLBase::setColor(color)); + } + + /** + * @brief Set wireframe color + * @return Reference to self (for method chaining) + * + * Initial value is @cpp 0x000000ff_rgbaf @ce. Expects that + * @ref Flag::Wireframe is enabled. + */ + MeshVisualizerGL3D& setWireframeColor(const Color4& color) { + return static_cast(Implementation::MeshVisualizerGLBase::setWireframeColor(color)); + } + + /** + * @brief Set wireframe width + * @return Reference to self (for method chaining) + * + * Value is in screen space (depending on @ref setViewportSize()), + * initial value is @cpp 1.0f @ce. Expects that @ref Flag::Wireframe is + * enabled. + */ + MeshVisualizerGL3D& setWireframeWidth(Float width) { + return static_cast(Implementation::MeshVisualizerGLBase::setWireframeWidth(width)); + } + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Set color map transformation + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * Offset and scale applied to the input value coming either from the + * @ref ObjectId attribute or @glsl gl_PrimitiveID @ce, resulting value + * is then used to fetch a color from a color map bound with + * @ref bindColorMapTexture(). Initial value is @cpp 1.0f/512.0f @ce + * and @cpp 1.0/256.0f @ce, meaning that for a 256-entry colormap the + * first 256 values get an exact color from it and the next values will + * be either clamped to last color or repeated depending on the color + * map texture wrapping mode. Expects that either + * @ref Flag::InstancedObjectId or @ref Flag::PrimitiveId / + * @ref Flag::PrimitiveIdFromVertexId is enabled. + * + * Note that this shader doesn't directly offer a + * @ref FlatGL::setObjectId() "setObjectId()" uniform that's used to + * offset the per-vertex / per-instance ID. Instead, you need to encode + * the base offset into the @p offset parameter. + * @requires_gles30 Object ID visualization requires integer attributes + * while primitive ID visualization requires the `gl_VertexID` / + * `gl_PrimitiveID` builtins, neither of which is available in + * OpenGL ES 2.0. + * @requires_webgl20 Object ID visualization requires integer + * attributes while primitive ID visualization requires at least + * the `gl_VertexID` builtin, neither of which is available in + * WebGL 1. + */ + MeshVisualizerGL3D& setColorMapTransformation(Float offset, Float scale) { + return static_cast(Implementation::MeshVisualizerGLBase::setColorMapTransformation(offset, scale)); + } + + /** + * @brief Bind a color map texture + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * See also @ref setColorMapTransformation(). Expects that either + * @ref Flag::InstancedObjectId or @ref Flag::PrimitiveId / + * @ref Flag::PrimitiveIdFromVertexId is enabled. + * @requires_gles30 Object ID visualization requires integer attributes + * while primitive ID visualization requires the `gl_VertexID` / + * `gl_PrimitiveID` builtins, neither of which is available in + * OpenGL ES 2.0. + * @requires_webgl20 Object ID visualization requires integer + * attributes while primitive ID visualization requires at least + * the `gl_VertexID` builtin, neither of which is available in + * WebGL 1. + */ + MeshVisualizerGL3D& bindColorMapTexture(GL::Texture2D& texture) { + return static_cast(Implementation::MeshVisualizerGLBase::bindColorMapTexture(texture)); + } + #endif + + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /** + * @brief Set line width + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * Value is in screen space (depending on @ref setViewportSize()), + * initial value is @cpp 1.0f @ce. Expects that + * @ref Flag::TangentDirection, + * @ref Flag::BitangentFromTangentDirection, + * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is + * enabled. + * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / + * @gl_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + MeshVisualizerGL3D& setLineWidth(Float width); + + /** + * @brief Set line length + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * Value is in object space, initial value is @cpp 1.0f @ce. Expects + * that @ref Flag::TangentDirection, + * @ref Flag::BitangentFromTangentDirection, + * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is + * enabled. + * @requires_gl32 Extension @gl_extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @gl_extension{ANDROID,extension_pack_es31a} / + * @gl_extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + MeshVisualizerGL3D& setLineLength(Float length); + #endif + + /** + * @brief Set line smoothness + * @return Reference to self (for method chaining) + * + * Value is in screen space (depending on @ref setViewportSize()), + * initial value is @cpp 2.0f @ce. Expects that @ref Flag::Wireframe, + * @ref Flag::TangentDirection, + * @ref Flag::BitangentFromTangentDirection, + * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is + * enabled. + */ + MeshVisualizerGL3D& setSmoothness(Float smoothness); + + private: + Int _transformationMatrixUniform{0}, + _projectionMatrixUniform{7}; + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + Int _normalMatrixUniform{8}, + _lineWidthUniform{9}, + _lineLengthUniform{10}; + #endif +}; + +/** @debugoperatorclassenum{MeshVisualizerGL2D,MeshVisualizerGL2D::Flag} */ +MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizerGL2D::Flag value); + +/** @debugoperatorclassenum{MeshVisualizerGL3D,MeshVisualizerGL3D::Flag} */ +MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizerGL3D::Flag value); + +/** @debugoperatorclassenum{MeshVisualizerGL2D,MeshVisualizerGL2D::Flags} */ +MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizerGL2D::Flags value); + +/** @debugoperatorclassenum{MeshVisualizerGL3D,MeshVisualizerGL3D::Flags} */ +MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, MeshVisualizerGL3D::Flags value); + +CORRADE_ENUMSET_OPERATORS(MeshVisualizerGL2D::Flags) +CORRADE_ENUMSET_OPERATORS(MeshVisualizerGL3D::Flags) + +}} + +#endif diff --git a/src/Magnum/Shaders/Phong.h b/src/Magnum/Shaders/Phong.h index b59537083..24a5cd9af 100644 --- a/src/Magnum/Shaders/Phong.h +++ b/src/Magnum/Shaders/Phong.h @@ -25,1026 +25,33 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file - * @brief Class @ref Magnum::Shaders::Phong + * @brief Typedef @ref Magnum::Shaders::Phong + * @m_deprecated_since_latest Use @ref Magnum/Shaders/PhongGL.h and the + * @ref Magnum::Shaders::PhongGL "PhongGL" class instead */ +#endif -#include "Magnum/GL/AbstractShaderProgram.h" -#include "Magnum/Shaders/Generic.h" -#include "Magnum/Shaders/visibility.h" - -namespace Magnum { namespace Shaders { - -/** -@brief Phong shader - -Uses ambient, diffuse and specular color or texture. For a colored mesh you -need to provide the @ref Position and @ref Normal attributes in your triangle -mesh. By default, the shader renders the mesh with a white color in an identity -transformation. Use @ref setTransformationMatrix(), @ref setNormalMatrix(), -@ref setProjectionMatrix(), @ref setLightPosition() and others to configure -the shader. - -@image html shaders-phong.png width=256px - -@section Shaders-Phong-colored Colored rendering - -Common mesh setup: - -@snippet MagnumShaders.cpp Phong-usage-colored1 - -Common rendering setup: - -@snippet MagnumShaders.cpp Phong-usage-colored2 - -@section Shaders-Phong-texture Textured rendering - -If you want to use textures, you need to provide also the -@ref TextureCoordinates attribute. Pass appropriate @ref Flag combination to -the constructor and then at render time don't forget to also call appropriate -subset of @ref bindAmbientTexture(), @ref bindDiffuseTexture() and -@ref bindSpecularTexture() (or the combined @ref bindTextures()). The texture -is multipled by the color, which is by default set to fully opaque white for -enabled textures. Mesh setup with a diffuse and a specular texture: - -@snippet MagnumShaders.cpp Phong-usage-texture1 - -Common rendering setup: - -@snippet MagnumShaders.cpp Phong-usage-texture2 - -@section Shaders-Phong-lights Light specification - -By default, the shader provides a single directional "fill" light, coming from -the center of the camera. Using the @p lightCount parameter in constructor, you -can specify how many lights you want, and then control light parameters using -@ref setLightPositions(), @ref setLightColors(), @ref setLightSpecularColors() -and @ref setLightRanges(). Light positions are specified as four-component -vectors, the last component distinguishing between directional and point -lights. - -
  • -Point lights are specified with camera-relative position and the last component -set to @cpp 1.0f @ce together with @ref setLightRanges() describing the -attenuation. The range corresponds to the @ref Trade::LightData::range() and -the attenuation is calculated as the following --- see -@ref Trade-LightData-attenuation for more information: @f[ - F_{att} = \frac{\operatorname{clamp}(1 - (\frac{d}{\color{m-info} R})^4, 0, 1)^2}{1 + d^2} -@f] - -If you use @ref Constants::inf() as a range (which is also the default), the -equation reduces down to a simple inverse square: @f[ - F_{att} = \lim_{{\color{m-info} R} \to \infty} \frac{{\color{m-dim} \operatorname{clamp}(} 1 \mathbin{\color{m-dim} -} {\color{m-dim} (\frac{d}{R})^4, 0, 1)^2}}{1 + d^2} = \frac{1}{1 + d^2} -@f] -
  • -Directional lights are specified with a camera-relative direction *to* the -light with the last component set to @cpp 0.0f @ce --- which effectively makes -@f$ d = 0 @f$ --- and are not affected by values from @ref setLightRanges() in -any way: @f[ - F_{att} = \lim_{d \to 0} \frac{{\color{m-dim} \operatorname{clamp}(} 1 \mathbin{\color{m-dim} -} {\color{m-dim} (\frac{d}{R})^4, 0, 1)^2}}{1 \mathbin{\color{m-dim} +} {\color{m-dim} d^2}} = 1 -@f] -
- -Light color and intensity, corresponding to @ref Trade::LightData::color() and -@ref Trade::LightData::intensity(), is meant to be multiplied together and -passed to @ref setLightColors() and @ref setLightSpecularColors(). - -The following example shows a three-light setup with one dim directional light -shining from the top and two stronger but range-limited point lights: - -@snippet MagnumShaders.cpp Phong-usage-lights - -@subsection Shaders-Phong-lights-ambient Ambient lights - -In order to avoid redundant uniform inputs, there's no dedicated way to specify -ambient lights. Instead, they are handled by the ambient color input, as the -math for ambient color and lights is equivalent. Add the ambient colors -together and reuse the diffuse texture in the @ref bindAmbientTexture() slot to -have it affected by the ambient as well: - -@snippet MagnumShaders.cpp Phong-usage-lights-ambient - -@subsection Shaders-Phong-lights-zero Zero lights - -As a special case, creating this shader with zero lights makes its output -equivalent to the @ref Flat3D shader --- only @ref setAmbientColor() and -@ref bindAmbientTexture() (if @ref Flag::AmbientTexture is enabled) are taken -into account, which corresponds to @ref Flat::setColor() and -@ref Flat::bindTexture(). This is useful to reduce complexity in apps that -render models with pre-baked lights. For instanced workflows using zero lights -means the @ref NormalMatrix instance attribute doesn't need to be supplied -either. In addition, enabling @ref Flag::VertexColor and using a default -ambient color with no texturing makes this shader equivalent to -@ref VertexColor. - -@see @ref Trade::MaterialType::Flat - - - -@m_class{m-note m-dim} - -@par - Attenuation based on constant/linear/quadratic factors (the - @ref Trade::LightData::attenuation() property) and spot lights - (@ref Trade::LightData::innerConeAngle(), - @ref Trade::LightData::outerConeAngle() "outerConeAngle()") are not - implemented at the moment. - -@section Shaders-Phong-alpha Alpha blending and masking - -Alpha / transparency is supported by the shader implicitly, but to have it -working on the framebuffer, you need to enable -@ref GL::Renderer::Feature::Blending and set up the blending function. See -@ref GL::Renderer::setBlendFunction() for details. - -To avoid specular highlights on transparent areas, specular alpha should be -always set to @cpp 0.0f @ce. On the other hand, non-zero specular alpha can be -for example used to render transparent materials which are still expected to -have specular highlights such as glass or soap bubbles. - -An alternative is to enable @ref Flag::AlphaMask and tune @ref setAlphaMask() -for simple binary alpha-masked drawing that doesn't require depth sorting or -blending enabled. Note that this feature is implemented using the GLSL -@glsl discard @ce operation which is known to have considerable performance -impact on some platforms. With proper depth sorting and blending you'll usually -get much better performance and output quality. - -For general alpha-masked drawing you need to provide an ambient texture with -alpha channel and set alpha channel of the diffuse/specular color to @cpp 0.0f @ce -so only ambient alpha will be taken into account. If you have a diffuse texture -combined with the alpha mask, you can use that texture for both ambient and -diffuse part and then separate the alpha like this: - -@snippet MagnumShaders.cpp Phong-usage-alpha - -@section Shaders-Phong-normal-mapping Normal mapping - -If you want to use normal textures, enable @ref Flag::NormalTexture and call -@ref bindNormalTexture(). In addition you need to supply per-vertex tangent and -bitangent direction: - -- either using a four-component @ref Tangent4 attribute, where the sign of - the fourth component defines handedness of tangent basis, as described in - @ref Trade::MeshAttribute::Tangent; -- or a using pair of three-component @ref Tangent and @ref Bitangent - attributes together with enabling @ref Flag::Bitangent - -If you supply just a three-component @ref Tangent attribute and no bitangents, -the shader will implicitly assume the fourth component to be @cpp 1.0f @ce, -forming a right-handed tangent space. This is a valid optimization when you -have full control over the bitangent orientation, but won't work with general -meshes. - -@m_class{m-note m-success} - -@par - You can also use the @ref MeshVisualizer3D shader to visualize and debug - per-vertex normal, tangent and binormal direction, among other things. - -The strength of the effect can be controlled by -@ref setNormalTextureScale(). See -@ref Trade::MaterialAttribute::NormalTextureScale for a description of the -factor is used. - -@section Shaders-Phong-object-id Object ID output - -The shader supports writing object ID to the framebuffer for object picking or -other annotation purposes. Enable it using @ref Flag::ObjectId and set up an -integer buffer attached to the @ref ObjectIdOutput attachment. If you have a -batch of meshes with different object IDs, enable @ref Flag::InstancedObjectId -and supply per-vertex IDs to the @ref ObjectId attribute. The output will -contain a sum of the per-vertex ID and ID coming from @ref setObjectId(). - -The functionality is practically the same as in the @ref Flat shader, see -@ref Shaders-Flat-object-id "its documentation" for more information and usage -example. - -@requires_gles30 Object ID output requires integer buffer attachments, which - are not available in OpenGL ES 2.0 or WebGL 1.0. - -@section Shaders-Phong-instancing Instanced rendering - -Enabling @ref Flag::InstancedTransformation will turn the shader into an -instanced one. It'll take per-instance transformation and normal matrix from -the @ref TransformationMatrix and @ref NormalMatrix attributes, applying those -before the matrix set by @ref setTransformationMatrix() and -@ref setNormalMatrix(). Besides that, @ref Flag::VertexColor (and the -@ref Color3 / @ref Color4) attributes can work as both per-vertex and -per-instance, and for texturing it's possible to have per-instance texture -offset taken from @ref TextureOffset when @ref Flag::InstancedTextureOffset is -enabled (similarly to transformation, applied before @ref setTextureMatrix()). -The snippet below shows adding a buffer with per-instance transformation to a -mesh --- note how a normal matrix attribute has to be populated and supplied as -well to ensure lighting works: - -@snippet MagnumShaders.cpp Phong-usage-instancing - -@requires_gl33 Extension @gl_extension{ARB,instanced_arrays} -@requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - @gl_extension{EXT,instanced_arrays} or @gl_extension{NV,instanced_arrays} - in OpenGL ES 2.0. -@requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} in WebGL - 1.0. - -@see @ref shaders -*/ -class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram { - public: - /** - * @brief Vertex position - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector3 "Vector3". - */ - typedef Generic3D::Position Position; - - /** - * @brief Normal direction - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector3 "Vector3". - */ - typedef Generic3D::Normal Normal; - - /** - * @brief Tangent direction - * @m_since{2019,10} - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4 - * attribute. If only a three-component attribute is used and - * @ref Flag::Bitangent is not enabled, it's the same as if - * @ref Tangent4 was specified with the fourth component always being - * @cpp 1.0f @ce. Used only if @ref Flag::NormalTexture is set. - * @see @ref Shaders-Phong-normal-mapping - */ - typedef Generic3D::Tangent Tangent; - - /** - * @brief Tangent direction with a bitangent sign - * @m_since_latest - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector4 "Vector4". Use either this or the @ref Tangent - * attribute. If @ref Flag::Bitangent is set, the fourth component is - * ignored and bitangents are taken from the @ref Bitangent attribute - * instead. Used only if @ref Flag::NormalTexture is set. - * @see @ref Shaders-Phong-normal-mapping - */ - typedef typename Generic3D::Tangent4 Tangent4; - - /** - * @brief Bitangent direction - * @m_since_latest - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4 - * attribute. Used only if both @ref Flag::NormalTexture and - * @ref Flag::Bitangent are set. - * @see @ref Shaders-Phong-normal-mapping - */ - typedef typename Generic3D::Bitangent Bitangent; - - /** - * @brief 2D texture coordinates - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector2 "Vector2", used only if at least one of - * @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture and - * @ref Flag::SpecularTexture is set. - */ - typedef Generic3D::TextureCoordinates TextureCoordinates; - - /** - * @brief Three-component vertex color - * @m_since{2019,10} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Color3. Use - * either this or the @ref Color4 attribute. Used only if - * @ref Flag::VertexColor is set. - */ - typedef Generic3D::Color3 Color3; - - /** - * @brief Four-component vertex color - * @m_since{2019,10} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Color4. Use - * either this or the @ref Color3 attribute. Used only if - * @ref Flag::VertexColor is set. - */ - typedef Generic3D::Color4 Color4; - - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief (Instanced) object ID - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. - * Used only if @ref Flag::InstancedObjectId is set. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. - */ - typedef Generic3D::ObjectId ObjectId; - #endif - - /** - * @brief (Instanced) transformation matrix - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Matrix4. - * Used only if @ref Flag::InstancedTransformation is set. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - */ - typedef Generic3D::TransformationMatrix TransformationMatrix; - - /** - * @brief (Instanced) normal matrix - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Matrix3x3. - * Used only if @ref Flag::InstancedTransformation is set. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - */ - typedef Generic3D::NormalMatrix NormalMatrix; - - /** - * @brief (Instanced) texture offset - * @m_since{2020,06} - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Vector2. Used - * only if @ref Flag::InstancedTextureOffset is set. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - */ - typedef typename Generic3D::TextureOffset TextureOffset; - - enum: UnsignedInt { - /** - * Color shader output. @ref shaders-generic "Generic output", - * present always. Expects three- or four-component floating-point - * or normalized buffer attachment. - * @m_since{2019,10} - */ - ColorOutput = Generic3D::ColorOutput, - - #ifndef MAGNUM_TARGET_GLES2 - /** - * Object ID shader output. @ref shaders-generic "Generic output", - * present only if @ref Flag::ObjectId is set. Expects a - * single-component unsigned integral attachment. Writes the value - * set in @ref setObjectId() there, see - * @ref Shaders-Phong-object-id for more information. - * @requires_gl30 Extension @gl_extension{EXT,texture_integer} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL - * 1.0. - * @m_since{2019,10} - */ - ObjectIdOutput = Generic3D::ObjectIdOutput - #endif - }; - - /** - * @brief Flag - * - * @see @ref Flags, @ref flags() - */ - enum class Flag: UnsignedShort { - /** - * Multiply ambient color with a texture. - * @see @ref setAmbientColor(), @ref bindAmbientTexture() - */ - AmbientTexture = 1 << 0, - - /** - * Multiply diffuse color with a texture. - * @see @ref setDiffuseColor(), @ref bindDiffuseTexture() - */ - DiffuseTexture = 1 << 1, - - /** - * Multiply specular color with a texture. - * @see @ref setSpecularColor(), @ref bindSpecularTexture() - */ - SpecularTexture = 1 << 2, - - /** - * Modify normals according to a texture. Requires the - * @ref Tangent attribute to be present. - * @m_since{2019,10} - */ - NormalTexture = 1 << 4, - - /** - * Enable alpha masking. If the combined fragment color has an - * alpha less than the value specified with @ref setAlphaMask(), - * given fragment is discarded. - * - * This uses the @glsl discard @ce operation which is known to have - * considerable performance impact on some platforms. While useful - * for cheap alpha masking that doesn't require depth sorting, - * with proper depth sorting and blending you'll usually get much - * better performance and output quality. - */ - AlphaMask = 1 << 3, - - /** - * Multiply diffuse color with a vertex color. Requires either - * the @ref Color3 or @ref Color4 attribute to be present. - * @m_since{2019,10} - */ - VertexColor = 1 << 5, - - /** - * Use the separate @ref Bitangent attribute for retrieving vertex - * bitangents. If this flag is not present, the last component of - * @ref Tangent4 is used to calculate bitangent direction. See - * @ref Shaders-Phong-normal-mapping for more information. - * @m_since_latest - */ - Bitangent = 1 << 11, - - /** - * Enable texture coordinate transformation. If this flag is set, - * the shader expects that at least one of - * @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture, - * @ref Flag::SpecularTexture or @ref Flag::NormalTexture is - * enabled as well. - * @see @ref setTextureMatrix() - * @m_since{2020,06} - */ - TextureTransformation = 1 << 6, - - #ifndef MAGNUM_TARGET_GLES2 - /** - * Enable object ID output. See @ref Shaders-Phong-object-id - * for more information. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL - * 1.0. - * @m_since{2019,10} - */ - ObjectId = 1 << 7, - - /** - * Instanced object ID. Retrieves a per-instance / per-vertex - * object ID from the @ref ObjectId attribute, outputting a sum of - * the per-vertex ID and ID coming from @ref setObjectId(). - * Implicitly enables @ref Flag::ObjectId. See - * @ref Shaders-Phong-object-id for more information. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL - * 1.0. - * @m_since{2020,06} - */ - InstancedObjectId = (1 << 8)|ObjectId, - #endif - - /** - * Instanced transformation. Retrieves a per-instance - * transformation and normal matrix from the - * @ref TransformationMatrix / @ref NormalMatrix attributes and - * uses them together with matrices coming from - * @ref setTransformationMatrix() and @ref setNormalMatrix() (first - * the per-instance, then the uniform matrix). See - * @ref Shaders-Phong-instancing for more information. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - * @m_since{2020,06} - */ - InstancedTransformation = 1 << 9, - - /** - * Instanced texture offset. Retrieves a per-instance offset vector - * from the @ref TextureOffset attribute and uses it together with - * the matrix coming from @ref setTextureMatrix() (first the - * per-instance vector, then the uniform matrix). Instanced texture - * scaling and rotation is not supported at the moment, you can - * specify that only via the uniform @ref setTextureMatrix(). - * Implicitly enables @ref Flag::TextureTransformation. See - * @ref Shaders-Phong-instancing for more information. - * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} - * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, - * @gl_extension{EXT,instanced_arrays} or - * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} - * in WebGL 1.0. - * @m_since{2020,06} - */ - InstancedTextureOffset = (1 << 10)|TextureTransformation - }; - - /** - * @brief Flags - * - * @see @ref flags() - */ - typedef Containers::EnumSet Flags; - - /** - * @brief Constructor - * @param flags Flags - * @param lightCount Count of light sources - */ - explicit Phong(Flags flags = {}, UnsignedInt lightCount = 1); - - /** - * @brief Construct without creating the underlying OpenGL object - * - * The constructed instance is equivalent to a moved-from state. Useful - * in cases where you will overwrite the instance later anyway. Move - * another object over it to make it useful. - * - * This function can be safely used for constructing (and later - * destructing) objects even without any OpenGL context being active. - * However note that this is a low-level and a potentially dangerous - * API, see the documentation of @ref NoCreate for alternatives. - */ - explicit Phong(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} - - /** @brief Copying is not allowed */ - Phong(const Phong&) = delete; - - /** @brief Move constructor */ - Phong(Phong&&) noexcept = default; - - /** @brief Copying is not allowed */ - Phong& operator=(const Phong&) = delete; - - /** @brief Move assignment */ - Phong& operator=(Phong&&) noexcept = default; - - /** @brief Flags */ - Flags flags() const { return _flags; } - - /** @brief Light count */ - UnsignedInt lightCount() const { return _lightCount; } - - /** - * @brief Set ambient color - * @return Reference to self (for method chaining) - * - * If @ref Flag::AmbientTexture is set, default value is - * @cpp 0xffffffff_rgbaf @ce and the color will be multiplied with - * ambient texture, otherwise default value is @cpp 0x00000000_rgbaf @ce. - * @see @ref bindAmbientTexture(), @ref Shaders-Phong-lights-ambient - */ - Phong& setAmbientColor(const Magnum::Color4& color); - - /** - * @brief Bind an ambient texture - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::AmbientTexture - * enabled. - * @see @ref bindTextures(), @ref setAmbientColor(), - * @ref Shaders-Phong-lights-ambient - */ - Phong& bindAmbientTexture(GL::Texture2D& texture); - - /** - * @brief Set diffuse color - * @return Reference to self (for method chaining) - * - * Initial value is @cpp 0xffffffff_rgbaf @ce. If @ref lightCount() is - * zero, this function is a no-op, as diffuse color doesn't contribute - * to the output in that case. - * @see @ref bindDiffuseTexture() - */ - Phong& setDiffuseColor(const Magnum::Color4& color); - - /** - * @brief Bind a diffuse texture - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::DiffuseTexture - * enabled. If @ref lightCount() is zero, this function is a no-op, as - * diffuse color doesn't contribute to the output in that case. - * @see @ref bindTextures(), @ref setDiffuseColor() - */ - Phong& bindDiffuseTexture(GL::Texture2D& texture); - - /** - * @brief Set normal texture scale - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Affects strength of the normal mapping. Initial value is - * @cpp 1.0f @ce, meaning the normal texture is not changed in any way; - * a value of @cpp 0.0f @ce disables the normal texture effect - * altogether. - * - * Expects that the shader was created with @ref Flag::NormalTexture - * enabled. If @ref lightCount() is zero, this function is a no-op, as - * normals don't contribute to the output in that case. - * @see @ref Shaders-Phong-normal-mapping, @ref bindNormalTexture(), - * @ref Trade::MaterialAttribute::NormalTextureScale - */ - Phong& setNormalTextureScale(Float scale); - - /** - * @brief Bind a normal texture - * @return Reference to self (for method chaining) - * @m_since{2019,10} - * - * Expects that the shader was created with @ref Flag::NormalTexture - * enabled and the @ref Tangent attribute was supplied. If - * @ref lightCount() is zero, this function is a no-op, as normals - * don't contribute to the output in that case. - * @see @ref Shaders-Phong-normal-mapping, - * @ref bindTextures(), @ref setNormalTextureScale() - */ - Phong& bindNormalTexture(GL::Texture2D& texture); - - /** - * @brief Set specular color - * @return Reference to self (for method chaining) - * - * Initial value is @cpp 0xffffff00_rgbaf @ce. Color will be multiplied - * with specular texture if @ref Flag::SpecularTexture is set. If you - * want to have a fully diffuse material, set specular color to - * @cpp 0x00000000_rgbaf @ce. If @ref lightCount() is zero, this - * function is a no-op, as specular color doesn't contribute to the - * output in that case. - * @see @ref bindSpecularTexture() - */ - Phong& setSpecularColor(const Magnum::Color4& color); - - /** - * @brief Bind a specular texture - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::SpecularTexture - * enabled. If @ref lightCount() is zero, this function is a no-op, as - * specular color doesn't contribute to the output in that case. - * @see @ref bindTextures(), @ref setSpecularColor() - */ - Phong& bindSpecularTexture(GL::Texture2D& texture); - - /** - * @brief Bind textures - * @return Reference to self (for method chaining) - * - * A particular texture has effect only if particular texture flag from - * @ref Phong::Flag "Flag" is set, you can use @cpp nullptr @ce for the - * rest. Expects that the shader was created with at least one of - * @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture, - * @ref Flag::SpecularTexture or @ref Flag::NormalTexture enabled. More - * efficient than setting each texture separately. - * @see @ref bindAmbientTexture(), @ref bindDiffuseTexture(), - * @ref bindSpecularTexture(), @ref bindNormalTexture() - */ - Phong& bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal - #ifdef MAGNUM_BUILD_DEPRECATED - = nullptr - #endif - ); - - /** - * @brief Set shininess - * @return Reference to self (for method chaining) - * - * The larger value, the harder surface (smaller specular highlight). - * Initial value is @cpp 80.0f @ce. If @ref lightCount() is zero, this - * function is a no-op, as specular color doesn't contribute to the - * output in that case. - */ - Phong& setShininess(Float shininess); - - /** - * @brief Set alpha mask value - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::AlphaMask - * enabled. Fragments with alpha values smaller than the mask value - * will be discarded. Initial value is @cpp 0.5f @ce. See the flag - * documentation for further information. - * - * This corresponds to @m_class{m-doc-external} [glAlphaFunc()](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAlphaFunc.xml) - * in classic OpenGL. - * @m_keywords{glAlphaFunc()} - */ - Phong& setAlphaMask(Float mask); - - #ifndef MAGNUM_TARGET_GLES2 - /** - * @brief Set object ID - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::ObjectId - * enabled. Value set here is written to the @ref ObjectIdOutput, see - * @ref Shaders-Phong-object-id for more information. Default is - * @cpp 0 @ce. - * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} - * @requires_gles30 Object ID output requires integer support in - * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. - */ - Phong& setObjectId(UnsignedInt id); - #endif - - /** - * @brief Set transformation matrix - * @return Reference to self (for method chaining) - * - * You need to set also @ref setNormalMatrix() with a corresponding - * value. Initial value is an identity matrix. - */ - Phong& setTransformationMatrix(const Matrix4& matrix); - - /** - * @brief Set normal matrix - * @return Reference to self (for method chaining) - * - * The matrix doesn't need to be normalized, as renormalization is done - * per-fragment anyway. You need to set also - * @ref setTransformationMatrix() with a corresponding value. Initial - * value is an identity matrix. If @ref lightCount() is zero, this - * function is a no-op, as normals don't contribute to the output in - * that case. - * @see @ref Math::Matrix4::normalMatrix() - */ - Phong& setNormalMatrix(const Matrix3x3& matrix); - - /** - * @brief Set projection matrix - * @return Reference to self (for method chaining) - * - * Initial value is an identity matrix (i.e., an orthographic - * projection of the default @f$ [ -\boldsymbol{1} ; \boldsymbol{1} ] @f$ - * cube). - */ - Phong& setProjectionMatrix(const Matrix4& matrix); - - /** - * @brief Set texture coordinate transformation matrix - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * Expects that the shader was created with - * @ref Flag::TextureTransformation enabled. Initial value is an - * identity matrix. - */ - Phong& setTextureMatrix(const Matrix3& matrix); - - /** - * @brief Set light positions - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Depending on the fourth component, the value is treated as either a - *camera-relative position of a point light, if the fourth component is - * @cpp 1.0f @ce; or a direction *to* a directional light, if the - * fourth component is @cpp 0.0f @ce. Expects that the size of the - * @p positions array is the same as @ref lightCount(). Initial values - * are @cpp {0.0f, 0.0f, 1.0f, 0.0f} @ce --- a directional "fill" light - * coming from the camera. - * @see @ref Shaders-Phong-lights, @ref setLightPosition() - */ - Phong& setLightPositions(Containers::ArrayView positions); - - /** - * @overload - * @m_since_latest - */ - Phong& setLightPositions(std::initializer_list positions); - - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @brief @copybrief setLightPositions(Containers::ArrayView) - * @m_deprecated_since_latest Use @ref setLightPositions(Containers::ArrayView) - * instead. This function sets the fourth component to - * @cpp 0.0f @ce to preserve the original behavior as close as - * possible. - */ - CORRADE_DEPRECATED("use setLightPositions(Containers::ArrayView) instead") Phong& setLightPositions(Containers::ArrayView positions); - - /** - * @brief @copybrief setLightPositions(std::initializer_list) - * @m_deprecated_since_latest Use @ref setLightPositions(std::initializer_list) - * instead. This function sets the fourth component to - * @cpp 0.0f @ce to preserve the original behavior as close as - * possible. - */ - CORRADE_DEPRECATED("use setLightPositions(std::initializer_list) instead") Phong& setLightPositions(std::initializer_list positions); - #endif - - /** - * @brief Set position for given light - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Unlike @ref setLightPositions() updates just a single light - * position. If updating more than one light, prefer the batch function - * instead to reduce the count of GL API calls. Expects that @p id is - * less than @ref lightCount(). - */ - Phong& setLightPosition(UnsignedInt id, const Vector4& position); - - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @brief @copybrief setLightPosition(UnsignedInt, const Vector4&) - * @m_deprecated_since_latest Use @ref setLightPosition(UnsignedInt, const Vector4&) - * instead. This function sets the fourth component to - * @cpp 0.0f @ce to preserve the original behavior as close as - * possible. - */ - CORRADE_DEPRECATED("use setLightPosition(UnsignedInt, const Vector4&) instead") Phong& setLightPosition(UnsignedInt id, const Vector3& position); - - /** - * @brief Set light position - * @m_deprecated_since_latest Use @ref setLightPositions(std::initializer_list) - * with a single item instead --- it's short enough to not warrant - * the existence of a dedicated overload. This function sets the - * fourth component to @cpp 0.0f @ce to preserve the original - * behavior as close as possible. - */ - CORRADE_DEPRECATED("use setLightPositions(std::initializer_list) instead") Phong& setLightPosition(const Vector3& position); - #endif - - /** - * @brief Set light colors - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Initial values are @cpp 0xffffff_rgbf @ce. Expects that the size - * of the @p colors array is the same as @ref lightCount(). - * @see @ref Shaders-Phong-lights, @ref setLightColor() - */ - Phong& setLightColors(Containers::ArrayView colors); - - /** - * @overload - * @m_since_latest - */ - Phong& setLightColors(std::initializer_list colors); - - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @brief @copybrief setLightColors(Containers::ArrayView) - * @m_deprecated_since_latest Use @ref setLightColors(Containers::ArrayView) - * instead. The alpha channel isn't used in any way. - */ - CORRADE_DEPRECATED("use setLightColors(Containers::ArrayView) instead") Phong& setLightColors(Containers::ArrayView colors); - - /** - * @brief @copybrief setLightColors(std::initializer_list) - * @m_deprecated_since_latest Use @ref setLightColors(std::initializer_list) - * instead. The alpha channel isn't used in any way. - */ - CORRADE_DEPRECATED("use setLightColors(std::initializer_list) instead") Phong& setLightColors(std::initializer_list colors); - #endif - - /** - * @brief Set color for given light - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Unlike @ref setLightColors() updates just a single light color. If - * updating more than one light, prefer the batch function instead to - * reduce the count of GL API calls. Expects that @p id is less than - * @ref lightCount(). - */ - Phong& setLightColor(UnsignedInt id, const Magnum::Color3& color); - - #ifdef MAGNUM_BUILD_DEPRECATED - /** - * @brief @copybrief setLightColor(UnsignedInt, const Magnum::Color3&) - * @m_deprecated_since_latest Use @ref setLightColor(UnsignedInt, const Magnum::Color3&) - * instead. The alpha channel isn't used in any way. - */ - CORRADE_DEPRECATED("use setLightColor(UnsignedInt, const Magnum::Color3&) instead") Phong& setLightColor(UnsignedInt id, const Magnum::Color4& color); - - /** - * @brief Set light color - * @m_deprecated_since_latest Use @ref setLightColors(std::initializer_list) - * with a single item instead --- it's short enough to not warrant - * the existence of a dedicated overload. The alpha channel isn't - * used in any way. - */ - CORRADE_DEPRECATED("use setLightColor(std::initializer_list) instead") Phong& setLightColor(const Magnum::Color4& color); - #endif - - /** - * @brief Set light specular colors - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Usually you'd set this value to the same as @ref setLightColors(), - * but it allows for greater flexibility such as disabling specular - * highlights on certain lights. Initial values are - * @cpp 0xffffff_rgbf @ce. Expects that the size of the @p colors array - * is the same as @ref lightCount(). - * @see @ref Shaders-Phong-lights, @ref setLightColor() - */ - Phong& setLightSpecularColors(Containers::ArrayView colors); - - /** - * @overload - * @m_since_latest - */ - Phong& setLightSpecularColors(std::initializer_list colors); - - /** - * @brief Set specular color for given light - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Unlike @ref setLightSpecularColors() updates just a single light - * color. If updating more than one light, prefer the batch function - * instead to reduce the count of GL API calls. Expects that @p id is - * less than @ref lightCount(). - */ - Phong& setLightSpecularColor(UnsignedInt id, const Magnum::Color3& color); - - /** - * @brief Set light attenuation ranges - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Initial values are @ref Constants::inf(). Expects that the size of - * the @p ranges array is the same as @ref lightCount(). - * @see @ref Shaders-Phong-lights, @ref setLightRange() - */ - Phong& setLightRanges(Containers::ArrayView ranges); - - /** - * @overload - * @m_since_latest - */ - Phong& setLightRanges(std::initializer_list ranges); - - /** - * @brief Set attenuation range for given light - * @return Reference to self (for method chaining) - * @m_since_latest - * - * Unlike @ref setLightRanges() updates just a single light range. If - * updating more than one light, prefer the batch function instead to - * reduce the count of GL API calls. Expects that @p id is less than - * @ref lightCount(). - */ - Phong& setLightRange(UnsignedInt id, Float range); +#include "Magnum/configure.h" - private: - /* Prevent accidentally calling irrelevant functions */ - #ifndef MAGNUM_TARGET_GLES - using GL::AbstractShaderProgram::drawTransformFeedback; - #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - using GL::AbstractShaderProgram::dispatchCompute; - #endif +#ifdef MAGNUM_BUILD_DEPRECATED +#include - Flags _flags; - UnsignedInt _lightCount{}; - Int _transformationMatrixUniform{0}, - _projectionMatrixUniform{1}, - _normalMatrixUniform{2}, - _textureMatrixUniform{3}, - _ambientColorUniform{4}, - _diffuseColorUniform{5}, - _specularColorUniform{6}, - _shininessUniform{7}, - _normalTextureScaleUniform{8}, - _alphaMaskUniform{9}; - #ifndef MAGNUM_TARGET_GLES2 - Int _objectIdUniform{10}; - #endif - Int _lightPositionsUniform{11}, - _lightColorsUniform, /* 11 + lightCount, set in the constructor */ - _lightSpecularColorsUniform, /* 11 + 2*lightCount */ - _lightRangesUniform; /* 11 + 3*lightCount */ -}; +#include "Magnum/Shaders/PhongGL.h" -/** @debugoperatorclassenum{Phong,Phong::Flag} */ -MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, Phong::Flag value); +CORRADE_DEPRECATED_FILE("use Magnum/Shaders/PhongGL.h and the PhongGL class instead") -/** @debugoperatorclassenum{Phong,Phong::Flags} */ -MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, Phong::Flags value); +namespace Magnum { namespace Shaders { -CORRADE_ENUMSET_OPERATORS(Phong::Flags) +/** @brief @copybrief PhongGL + * @m_deprecated_since_latest Use @ref PhongGL instead. + */ +typedef CORRADE_DEPRECATED("use PhongGL instead") PhongGL Phong; }} +#else +#error use Magnum/Shaders/PhongGL.h and the PhongGL class instead +#endif #endif diff --git a/src/Magnum/Shaders/Phong.cpp b/src/Magnum/Shaders/PhongGL.cpp similarity index 75% rename from src/Magnum/Shaders/Phong.cpp rename to src/Magnum/Shaders/PhongGL.cpp index 6cb4505a0..4dfa76ae3 100644 --- a/src/Magnum/Shaders/Phong.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "Phong.h" +#include "PhongGL.h" #if defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_BUILD_DEPRECATED) #include @@ -55,16 +55,16 @@ namespace { }; } -Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _lightCount{lightCount}, _lightColorsUniform{_lightPositionsUniform + Int(lightCount)}, _lightSpecularColorsUniform{_lightPositionsUniform + 2*Int(lightCount)}, _lightRangesUniform{_lightPositionsUniform + 3*Int(lightCount)} { +PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _lightCount{lightCount}, _lightColorsUniform{_lightPositionsUniform + Int(lightCount)}, _lightSpecularColorsUniform{_lightPositionsUniform + 2*Int(lightCount)}, _lightRangesUniform{_lightPositionsUniform + 3*Int(lightCount)} { CORRADE_ASSERT(!(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)), - "Shaders::Phong: texture transformation enabled but the shader is not textured", ); + "Shaders::PhongGL: texture transformation enabled but the shader is not textured", ); #ifdef MAGNUM_BUILD_STATIC /* Import resources on static build, if not already */ - if(!Utility::Resource::hasGroup("MagnumShaders")) + if(!Utility::Resource::hasGroup("MagnumShadersGL")) importShaderResources(); #endif - Utility::Resource rs("MagnumShaders"); + Utility::Resource rs("MagnumShadersGL"); #ifndef MAGNUM_TARGET_GLES const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); @@ -275,121 +275,121 @@ Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _l #endif } -Phong& Phong::setAmbientColor(const Magnum::Color4& color) { +PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) { setUniform(_ambientColorUniform, color); return *this; } -Phong& Phong::bindAmbientTexture(GL::Texture2D& texture) { +PhongGL& PhongGL::bindAmbientTexture(GL::Texture2D& texture) { CORRADE_ASSERT(_flags & Flag::AmbientTexture, - "Shaders::Phong::bindAmbientTexture(): the shader was not created with ambient texture enabled", *this); + "Shaders::PhongGL::bindAmbientTexture(): the shader was not created with ambient texture enabled", *this); texture.bind(AmbientTextureUnit); return *this; } -Phong& Phong::setDiffuseColor(const Magnum::Color4& color) { +PhongGL& PhongGL::setDiffuseColor(const Magnum::Color4& color) { if(_lightCount) setUniform(_diffuseColorUniform, color); return *this; } -Phong& Phong::bindDiffuseTexture(GL::Texture2D& texture) { +PhongGL& PhongGL::bindDiffuseTexture(GL::Texture2D& texture) { CORRADE_ASSERT(_flags & Flag::DiffuseTexture, - "Shaders::Phong::bindDiffuseTexture(): the shader was not created with diffuse texture enabled", *this); + "Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled", *this); if(_lightCount) texture.bind(DiffuseTextureUnit); return *this; } -Phong& Phong::setSpecularColor(const Magnum::Color4& color) { +PhongGL& PhongGL::setSpecularColor(const Magnum::Color4& color) { if(_lightCount) setUniform(_specularColorUniform, color); return *this; } -Phong& Phong::bindSpecularTexture(GL::Texture2D& texture) { +PhongGL& PhongGL::bindSpecularTexture(GL::Texture2D& texture) { CORRADE_ASSERT(_flags & Flag::SpecularTexture, - "Shaders::Phong::bindSpecularTexture(): the shader was not created with specular texture enabled", *this); + "Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled", *this); if(_lightCount) texture.bind(SpecularTextureUnit); return *this; } -Phong& Phong::bindNormalTexture(GL::Texture2D& texture) { +PhongGL& PhongGL::bindNormalTexture(GL::Texture2D& texture) { CORRADE_ASSERT(_flags & Flag::NormalTexture, - "Shaders::Phong::bindNormalTexture(): the shader was not created with normal texture enabled", *this); + "Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled", *this); if(_lightCount) texture.bind(NormalTextureUnit); return *this; } -Phong& Phong::bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal) { +PhongGL& PhongGL::bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal) { CORRADE_ASSERT(_flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture), - "Shaders::Phong::bindTextures(): the shader was not created with any textures enabled", *this); + "Shaders::PhongGL::bindTextures(): the shader was not created with any textures enabled", *this); GL::AbstractTexture::bind(AmbientTextureUnit, {ambient, diffuse, specular, normal}); return *this; } -Phong& Phong::setShininess(Float shininess) { +PhongGL& PhongGL::setShininess(Float shininess) { if(_lightCount) setUniform(_shininessUniform, shininess); return *this; } -Phong& Phong::setNormalTextureScale(const Float scale) { +PhongGL& PhongGL::setNormalTextureScale(const Float scale) { CORRADE_ASSERT(_flags & Flag::NormalTexture, - "Shaders::Phong::setNormalTextureScale(): the shader was not created with normal texture enabled", *this); + "Shaders::PhongGL::setNormalTextureScale(): the shader was not created with normal texture enabled", *this); if(_lightCount) setUniform(_normalTextureScaleUniform, scale); return *this; } -Phong& Phong::setAlphaMask(Float mask) { +PhongGL& PhongGL::setAlphaMask(Float mask) { CORRADE_ASSERT(_flags & Flag::AlphaMask, - "Shaders::Phong::setAlphaMask(): the shader was not created with alpha mask enabled", *this); + "Shaders::PhongGL::setAlphaMask(): the shader was not created with alpha mask enabled", *this); setUniform(_alphaMaskUniform, mask); return *this; } #ifndef MAGNUM_TARGET_GLES2 -Phong& Phong::setObjectId(UnsignedInt id) { +PhongGL& PhongGL::setObjectId(UnsignedInt id) { CORRADE_ASSERT(_flags & Flag::ObjectId, - "Shaders::Phong::setObjectId(): the shader was not created with object ID enabled", *this); + "Shaders::PhongGL::setObjectId(): the shader was not created with object ID enabled", *this); setUniform(_objectIdUniform, id); return *this; } #endif -Phong& Phong::setTransformationMatrix(const Matrix4& matrix) { +PhongGL& PhongGL::setTransformationMatrix(const Matrix4& matrix) { setUniform(_transformationMatrixUniform, matrix); return *this; } -Phong& Phong::setNormalMatrix(const Matrix3x3& matrix) { +PhongGL& PhongGL::setNormalMatrix(const Matrix3x3& matrix) { if(_lightCount) setUniform(_normalMatrixUniform, matrix); return *this; } -Phong& Phong::setProjectionMatrix(const Matrix4& matrix) { +PhongGL& PhongGL::setProjectionMatrix(const Matrix4& matrix) { setUniform(_projectionMatrixUniform, matrix); return *this; } -Phong& Phong::setTextureMatrix(const Matrix3& matrix) { +PhongGL& PhongGL::setTextureMatrix(const Matrix3& matrix) { CORRADE_ASSERT(_flags & Flag::TextureTransformation, - "Shaders::Phong::setTextureMatrix(): the shader was not created with texture transformation enabled", *this); + "Shaders::PhongGL::setTextureMatrix(): the shader was not created with texture transformation enabled", *this); setUniform(_textureMatrixUniform, matrix); return *this; } -Phong& Phong::setLightPositions(const Containers::ArrayView positions) { +PhongGL& PhongGL::setLightPositions(const Containers::ArrayView positions) { CORRADE_ASSERT(_lightCount == positions.size(), - "Shaders::Phong::setLightPositions(): expected" << _lightCount << "items but got" << positions.size(), *this); + "Shaders::PhongGL::setLightPositions(): expected" << _lightCount << "items but got" << positions.size(), *this); if(_lightCount) setUniform(_lightPositionsUniform, positions); return *this; } /* It's light, but can't be in the header because MSVC needs to know the size of Vector3 for the initializer list use */ -Phong& Phong::setLightPositions(const std::initializer_list positions) { +PhongGL& PhongGL::setLightPositions(const std::initializer_list positions) { return setLightPositions(Containers::arrayView(positions)); } #ifdef MAGNUM_BUILD_DEPRECATED -Phong& Phong::setLightPositions(const Containers::ArrayView positions) { +PhongGL& PhongGL::setLightPositions(const Containers::ArrayView positions) { Containers::Array fourComponent{NoInit, positions.size()}; for(std::size_t i = 0; i != positions.size(); ++i) fourComponent[i] = Vector4{positions[i], 0.0f}; @@ -397,40 +397,40 @@ Phong& Phong::setLightPositions(const Containers::ArrayView posit return *this; } -Phong& Phong::setLightPositions(const std::initializer_list positions) { +PhongGL& PhongGL::setLightPositions(const std::initializer_list positions) { CORRADE_IGNORE_DEPRECATED_PUSH return setLightPositions(Containers::arrayView(positions)); CORRADE_IGNORE_DEPRECATED_POP } #endif -Phong& Phong::setLightPosition(const UnsignedInt id, const Vector4& position) { +PhongGL& PhongGL::setLightPosition(const UnsignedInt id, const Vector4& position) { CORRADE_ASSERT(id < _lightCount, - "Shaders::Phong::setLightPosition(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); + "Shaders::PhongGL::setLightPosition(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); setUniform(_lightPositionsUniform + id, position); return *this; } #ifdef MAGNUM_BUILD_DEPRECATED -Phong& Phong::setLightPosition(UnsignedInt id, const Vector3& position) { +PhongGL& PhongGL::setLightPosition(UnsignedInt id, const Vector3& position) { return setLightPosition(id, Vector4{position, 0.0f}); } -Phong& Phong::setLightPosition(const Vector3& position) { +PhongGL& PhongGL::setLightPosition(const Vector3& position) { /* Use the list variant to check the shader really has just one light */ return setLightPositions({Vector4{position, 0.0f}}); } #endif -Phong& Phong::setLightColors(const Containers::ArrayView colors) { +PhongGL& PhongGL::setLightColors(const Containers::ArrayView colors) { CORRADE_ASSERT(_lightCount == colors.size(), - "Shaders::Phong::setLightColors(): expected" << _lightCount << "items but got" << colors.size(), *this); + "Shaders::PhongGL::setLightColors(): expected" << _lightCount << "items but got" << colors.size(), *this); if(_lightCount) setUniform(_lightColorsUniform, colors); return *this; } #ifdef MAGNUM_BUILD_DEPRECATED -Phong& Phong::setLightColors(const Containers::ArrayView colors) { +PhongGL& PhongGL::setLightColors(const Containers::ArrayView colors) { Containers::Array threeComponent{NoInit, colors.size()}; for(std::size_t i = 0; i != colors.size(); ++i) threeComponent[i] = colors[i].rgb(); @@ -438,77 +438,77 @@ Phong& Phong::setLightColors(const Containers::ArrayView c return *this; } -Phong& Phong::setLightColors(const std::initializer_list colors) { +PhongGL& PhongGL::setLightColors(const std::initializer_list colors) { CORRADE_IGNORE_DEPRECATED_PUSH return setLightColors(Containers::arrayView(colors)); CORRADE_IGNORE_DEPRECATED_POP } #endif -Phong& Phong::setLightColors(const std::initializer_list colors) { +PhongGL& PhongGL::setLightColors(const std::initializer_list colors) { return setLightColors(Containers::arrayView(colors)); } -Phong& Phong::setLightColor(const UnsignedInt id, const Magnum::Color3& color) { +PhongGL& PhongGL::setLightColor(const UnsignedInt id, const Magnum::Color3& color) { CORRADE_ASSERT(id < _lightCount, - "Shaders::Phong::setLightColor(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); + "Shaders::PhongGL::setLightColor(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); setUniform(_lightColorsUniform + id, color); return *this; } #ifdef MAGNUM_BUILD_DEPRECATED -Phong& Phong::setLightColor(UnsignedInt id, const Magnum::Color4& color) { +PhongGL& PhongGL::setLightColor(UnsignedInt id, const Magnum::Color4& color) { return setLightColor(id, color.rgb()); } -Phong& Phong::setLightColor(const Magnum::Color4& color) { +PhongGL& PhongGL::setLightColor(const Magnum::Color4& color) { /* Use the list variant to check the shader really has just one light */ return setLightColors({color.rgb()}); } #endif -Phong& Phong::setLightSpecularColors(const Containers::ArrayView colors) { +PhongGL& PhongGL::setLightSpecularColors(const Containers::ArrayView colors) { CORRADE_ASSERT(_lightCount == colors.size(), - "Shaders::Phong::setLightSpecularColors(): expected" << _lightCount << "items but got" << colors.size(), *this); + "Shaders::PhongGL::setLightSpecularColors(): expected" << _lightCount << "items but got" << colors.size(), *this); if(_lightCount) setUniform(_lightSpecularColorsUniform, colors); return *this; } -Phong& Phong::setLightSpecularColors(const std::initializer_list colors) { +PhongGL& PhongGL::setLightSpecularColors(const std::initializer_list colors) { return setLightSpecularColors(Containers::arrayView(colors)); } -Phong& Phong::setLightSpecularColor(const UnsignedInt id, const Magnum::Color3& color) { +PhongGL& PhongGL::setLightSpecularColor(const UnsignedInt id, const Magnum::Color3& color) { CORRADE_ASSERT(id < _lightCount, - "Shaders::Phong::setLightSpecularColor(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); + "Shaders::PhongGL::setLightSpecularColor(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); setUniform(_lightSpecularColorsUniform + id, color); return *this; } -Phong& Phong::setLightRanges(const Containers::ArrayView ranges) { +PhongGL& PhongGL::setLightRanges(const Containers::ArrayView ranges) { CORRADE_ASSERT(_lightCount == ranges.size(), - "Shaders::Phong::setLightRanges(): expected" << _lightCount << "items but got" << ranges.size(), *this); + "Shaders::PhongGL::setLightRanges(): expected" << _lightCount << "items but got" << ranges.size(), *this); if(_lightCount) setUniform(_lightRangesUniform, ranges); return *this; } -Phong& Phong::setLightRanges(const std::initializer_list ranges) { +PhongGL& PhongGL::setLightRanges(const std::initializer_list ranges) { return setLightRanges(Containers::arrayView(ranges)); } -Phong& Phong::setLightRange(const UnsignedInt id, const Float range) { +PhongGL& PhongGL::setLightRange(const UnsignedInt id, const Float range) { CORRADE_ASSERT(id < _lightCount, - "Shaders::Phong::setLightRange(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); + "Shaders::PhongGL::setLightRange(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); setUniform(_lightRangesUniform + id, range); return *this; } -Debug& operator<<(Debug& debug, const Phong::Flag value) { - debug << "Shaders::Phong::Flag" << Debug::nospace; +Debug& operator<<(Debug& debug, const PhongGL::Flag value) { + debug << "Shaders::PhongGL::Flag" << Debug::nospace; switch(value) { /* LCOV_EXCL_START */ - #define _c(v) case Phong::Flag::v: return debug << "::" #v; + #define _c(v) case PhongGL::Flag::v: return debug << "::" #v; _c(AmbientTexture) _c(DiffuseTexture) _c(SpecularTexture) @@ -530,22 +530,22 @@ Debug& operator<<(Debug& debug, const Phong::Flag value) { return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } -Debug& operator<<(Debug& debug, const Phong::Flags value) { - return Containers::enumSetDebugOutput(debug, value, "Shaders::Phong::Flags{}", { - Phong::Flag::AmbientTexture, - Phong::Flag::DiffuseTexture, - Phong::Flag::SpecularTexture, - Phong::Flag::NormalTexture, - Phong::Flag::Bitangent, - Phong::Flag::AlphaMask, - Phong::Flag::VertexColor, - Phong::Flag::InstancedTextureOffset, /* Superset of TextureTransformation */ - Phong::Flag::TextureTransformation, +Debug& operator<<(Debug& debug, const PhongGL::Flags value) { + return Containers::enumSetDebugOutput(debug, value, "Shaders::PhongGL::Flags{}", { + PhongGL::Flag::AmbientTexture, + PhongGL::Flag::DiffuseTexture, + PhongGL::Flag::SpecularTexture, + PhongGL::Flag::NormalTexture, + PhongGL::Flag::Bitangent, + PhongGL::Flag::AlphaMask, + PhongGL::Flag::VertexColor, + PhongGL::Flag::InstancedTextureOffset, /* Superset of TextureTransformation */ + PhongGL::Flag::TextureTransformation, #ifndef MAGNUM_TARGET_GLES2 - Phong::Flag::InstancedObjectId, /* Superset of ObjectId */ - Phong::Flag::ObjectId, + PhongGL::Flag::InstancedObjectId, /* Superset of ObjectId */ + PhongGL::Flag::ObjectId, #endif - Phong::Flag::InstancedTransformation}); + PhongGL::Flag::InstancedTransformation}); } }} diff --git a/src/Magnum/Shaders/PhongGL.h b/src/Magnum/Shaders/PhongGL.h new file mode 100644 index 000000000..65d4990bc --- /dev/null +++ b/src/Magnum/Shaders/PhongGL.h @@ -0,0 +1,1052 @@ +#ifndef Magnum_Shaders_PhongGL_h +#define Magnum_Shaders_PhongGL_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Shaders::PhongGL + * @m_since_latest + */ + +#include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/Shaders/GenericGL.h" +#include "Magnum/Shaders/visibility.h" + +namespace Magnum { namespace Shaders { + +/** +@brief Phong OpenGL shader +@m_since_latest + +Uses ambient, diffuse and specular color or texture. For a colored mesh you +need to provide the @ref Position and @ref Normal attributes in your triangle +mesh. By default, the shader renders the mesh with a white color in an identity +transformation. Use @ref setTransformationMatrix(), @ref setNormalMatrix(), +@ref setProjectionMatrix(), @ref setLightPosition() and others to configure +the shader. + +@image html shaders-phong.png width=256px + +@section Shaders-PhongGL-colored Colored rendering + +Common mesh setup: + +@snippet MagnumShaders-gl.cpp PhongGL-usage-colored1 + +Common rendering setup: + +@snippet MagnumShaders-gl.cpp PhongGL-usage-colored2 + +@section Shaders-PhongGL-texture Textured rendering + +If you want to use textures, you need to provide also the +@ref TextureCoordinates attribute. Pass appropriate @ref Flag combination to +the constructor and then at render time don't forget to also call appropriate +subset of @ref bindAmbientTexture(), @ref bindDiffuseTexture() and +@ref bindSpecularTexture() (or the combined @ref bindTextures()). The texture +is multipled by the color, which is by default set to fully opaque white for +enabled textures. Mesh setup with a diffuse and a specular texture: + +@snippet MagnumShaders-gl.cpp PhongGL-usage-texture1 + +Common rendering setup: + +@snippet MagnumShaders-gl.cpp PhongGL-usage-texture2 + +@section Shaders-PhongGL-lights Light specification + +By default, the shader provides a single directional "fill" light, coming from +the center of the camera. Using the @p lightCount parameter in constructor, you +can specify how many lights you want, and then control light parameters using +@ref setLightPositions(), @ref setLightColors(), @ref setLightSpecularColors() +and @ref setLightRanges(). Light positions are specified as four-component +vectors, the last component distinguishing between directional and point +lights. + +
  • +Point lights are specified with camera-relative position and the last component +set to @cpp 1.0f @ce together with @ref setLightRanges() describing the +attenuation. The range corresponds to the @ref Trade::LightData::range() and +the attenuation is calculated as the following --- see +@ref Trade-LightData-attenuation for more information: @f[ + F_{att} = \frac{\operatorname{clamp}(1 - (\frac{d}{\color{m-info} R})^4, 0, 1)^2}{1 + d^2} +@f] + +If you use @ref Constants::inf() as a range (which is also the default), the +equation reduces down to a simple inverse square: @f[ + F_{att} = \lim_{{\color{m-info} R} \to \infty} \frac{{\color{m-dim} \operatorname{clamp}(} 1 \mathbin{\color{m-dim} -} {\color{m-dim} (\frac{d}{R})^4, 0, 1)^2}}{1 + d^2} = \frac{1}{1 + d^2} +@f] +
  • +Directional lights are specified with a camera-relative direction *to* the +light with the last component set to @cpp 0.0f @ce --- which effectively makes +@f$ d = 0 @f$ --- and are not affected by values from @ref setLightRanges() in +any way: @f[ + F_{att} = \lim_{d \to 0} \frac{{\color{m-dim} \operatorname{clamp}(} 1 \mathbin{\color{m-dim} -} {\color{m-dim} (\frac{d}{R})^4, 0, 1)^2}}{1 \mathbin{\color{m-dim} +} {\color{m-dim} d^2}} = 1 +@f] +
+ +Light color and intensity, corresponding to @ref Trade::LightData::color() and +@ref Trade::LightData::intensity(), is meant to be multiplied together and +passed to @ref setLightColors() and @ref setLightSpecularColors(). + +The following example shows a three-light setup with one dim directional light +shining from the top and two stronger but range-limited point lights: + +@snippet MagnumShaders-gl.cpp PhongGL-usage-lights + +@subsection Shaders-PhongGL-lights-ambient Ambient lights + +In order to avoid redundant uniform inputs, there's no dedicated way to specify +ambient lights. Instead, they are handled by the ambient color input, as the +math for ambient color and lights is equivalent. Add the ambient colors +together and reuse the diffuse texture in the @ref bindAmbientTexture() slot to +have it affected by the ambient as well: + +@snippet MagnumShaders-gl.cpp PhongGL-usage-lights-ambient + +@subsection Shaders-PhongGL-lights-zero Zero lights + +As a special case, creating this shader with zero lights makes its output +equivalent to the @ref FlatGL3D shader --- only @ref setAmbientColor() and +@ref bindAmbientTexture() (if @ref Flag::AmbientTexture is enabled) are taken +into account, which corresponds to @ref FlatGL::setColor() and +@ref FlatGL::bindTexture(). This is useful to reduce complexity in apps that +render models with pre-baked lights. For instanced workflows using zero lights +means the @ref NormalMatrix instance attribute doesn't need to be supplied +either. In addition, enabling @ref Flag::VertexColor and using a default +ambient color with no texturing makes this shader equivalent to +@ref VertexColorGL. + +@see @ref Trade::MaterialType::Flat + + + +@m_class{m-note m-dim} + +@par + Attenuation based on constant/linear/quadratic factors (the + @ref Trade::LightData::attenuation() property) and spot lights + (@ref Trade::LightData::innerConeAngle(), + @ref Trade::LightData::outerConeAngle() "outerConeAngle()") are not + implemented at the moment. + +@section Shaders-PhongGL-alpha Alpha blending and masking + +Alpha / transparency is supported by the shader implicitly, but to have it +working on the framebuffer, you need to enable +@ref GL::Renderer::Feature::Blending and set up the blending function. See +@ref GL::Renderer::setBlendFunction() for details. + +To avoid specular highlights on transparent areas, specular alpha should be +always set to @cpp 0.0f @ce. On the other hand, non-zero specular alpha can be +for example used to render transparent materials which are still expected to +have specular highlights such as glass or soap bubbles. + +An alternative is to enable @ref Flag::AlphaMask and tune @ref setAlphaMask() +for simple binary alpha-masked drawing that doesn't require depth sorting or +blending enabled. Note that this feature is implemented using the GLSL +@glsl discard @ce operation which is known to have considerable performance +impact on some platforms. With proper depth sorting and blending you'll usually +get much better performance and output quality. + +For general alpha-masked drawing you need to provide an ambient texture with +alpha channel and set alpha channel of the diffuse/specular color to @cpp 0.0f @ce +so only ambient alpha will be taken into account. If you have a diffuse texture +combined with the alpha mask, you can use that texture for both ambient and +diffuse part and then separate the alpha like this: + +@snippet MagnumShaders-gl.cpp PhongGL-usage-alpha + +@section Shaders-PhongGL-normal-mapping Normal mapping + +If you want to use normal textures, enable @ref Flag::NormalTexture and call +@ref bindNormalTexture(). In addition you need to supply per-vertex tangent and +bitangent direction: + +- either using a four-component @ref Tangent4 attribute, where the sign of + the fourth component defines handedness of tangent basis, as described in + @ref Trade::MeshAttribute::Tangent; +- or a using pair of three-component @ref Tangent and @ref Bitangent + attributes together with enabling @ref Flag::Bitangent + +If you supply just a three-component @ref Tangent attribute and no bitangents, +the shader will implicitly assume the fourth component to be @cpp 1.0f @ce, +forming a right-handed tangent space. This is a valid optimization when you +have full control over the bitangent orientation, but won't work with general +meshes. + +@m_class{m-note m-success} + +@par + You can also use the @ref MeshVisualizerGL3D shader to visualize and debug + per-vertex normal, tangent and binormal direction, among other things. + +The strength of the effect can be controlled by +@ref setNormalTextureScale(). See +@ref Trade::MaterialAttribute::NormalTextureScale for a description of the +factor is used. + +@section Shaders-PhongGL-object-id Object ID output + +The shader supports writing object ID to the framebuffer for object picking or +other annotation purposes. Enable it using @ref Flag::ObjectId and set up an +integer buffer attached to the @ref ObjectIdOutput attachment. If you have a +batch of meshes with different object IDs, enable @ref Flag::InstancedObjectId +and supply per-vertex IDs to the @ref ObjectId attribute. The output will +contain a sum of the per-vertex ID and ID coming from @ref setObjectId(). + +The functionality is practically the same as in the @ref FlatGL shader, see +@ref Shaders-FlatGL-object-id "its documentation" for more information and usage +example. + +@requires_gles30 Object ID output requires integer buffer attachments, which + are not available in OpenGL ES 2.0 or WebGL 1.0. + +@section Shaders-PhongGL-instancing Instanced rendering + +Enabling @ref Flag::InstancedTransformation will turn the shader into an +instanced one. It'll take per-instance transformation and normal matrix from +the @ref TransformationMatrix and @ref NormalMatrix attributes, applying those +before the matrix set by @ref setTransformationMatrix() and +@ref setNormalMatrix(). Besides that, @ref Flag::VertexColor (and the +@ref Color3 / @ref Color4) attributes can work as both per-vertex and +per-instance, and for texturing it's possible to have per-instance texture +offset taken from @ref TextureOffset when @ref Flag::InstancedTextureOffset is +enabled (similarly to transformation, applied before @ref setTextureMatrix()). +The snippet below shows adding a buffer with per-instance transformation to a +mesh --- note how a normal matrix attribute has to be populated and supplied as +well to ensure lighting works: + +@snippet MagnumShaders-gl.cpp PhongGL-usage-instancing + +@requires_gl33 Extension @gl_extension{ARB,instanced_arrays} +@requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + @gl_extension{EXT,instanced_arrays} or @gl_extension{NV,instanced_arrays} + in OpenGL ES 2.0. +@requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} in WebGL + 1.0. + +@see @ref shaders +*/ +class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { + public: + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector3 "Vector3". + */ + typedef GenericGL3D::Position Position; + + /** + * @brief Normal direction + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector3 "Vector3". + */ + typedef GenericGL3D::Normal Normal; + + /** + * @brief Tangent direction + * @m_since{2019,10} + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4 + * attribute. If only a three-component attribute is used and + * @ref Flag::Bitangent is not enabled, it's the same as if + * @ref Tangent4 was specified with the fourth component always being + * @cpp 1.0f @ce. Used only if @ref Flag::NormalTexture is set. + * @see @ref Shaders-PhongGL-normal-mapping + */ + typedef GenericGL3D::Tangent Tangent; + + /** + * @brief Tangent direction with a bitangent sign + * @m_since_latest + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector4 "Vector4". Use either this or the @ref Tangent + * attribute. If @ref Flag::Bitangent is set, the fourth component is + * ignored and bitangents are taken from the @ref Bitangent attribute + * instead. Used only if @ref Flag::NormalTexture is set. + * @see @ref Shaders-PhongGL-normal-mapping + */ + typedef GenericGL3D::Tangent4 Tangent4; + + /** + * @brief Bitangent direction + * @m_since_latest + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector3 "Vector3". Use either this or the @ref Tangent4 + * attribute. Used only if both @ref Flag::NormalTexture and + * @ref Flag::Bitangent are set. + * @see @ref Shaders-PhongGL-normal-mapping + */ + typedef GenericGL3D::Bitangent Bitangent; + + /** + * @brief 2D texture coordinates + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector2 "Vector2", used only if at least one of + * @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture and + * @ref Flag::SpecularTexture is set. + */ + typedef GenericGL3D::TextureCoordinates TextureCoordinates; + + /** + * @brief Three-component vertex color + * @m_since{2019,10} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color3. Use + * either this or the @ref Color4 attribute. Used only if + * @ref Flag::VertexColor is set. + */ + typedef GenericGL3D::Color3 Color3; + + /** + * @brief Four-component vertex color + * @m_since{2019,10} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color4. Use + * either this or the @ref Color3 attribute. Used only if + * @ref Flag::VertexColor is set. + */ + typedef GenericGL3D::Color4 Color4; + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief (Instanced) object ID + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::UnsignedInt. + * Used only if @ref Flag::InstancedObjectId is set. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. + */ + typedef GenericGL3D::ObjectId ObjectId; + #endif + + /** + * @brief (Instanced) transformation matrix + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Matrix4. + * Used only if @ref Flag::InstancedTransformation is set. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + */ + typedef GenericGL3D::TransformationMatrix TransformationMatrix; + + /** + * @brief (Instanced) normal matrix + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Matrix3x3. + * Used only if @ref Flag::InstancedTransformation is set. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + */ + typedef GenericGL3D::NormalMatrix NormalMatrix; + + /** + * @brief (Instanced) texture offset + * @m_since{2020,06} + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Vector2. Used + * only if @ref Flag::InstancedTextureOffset is set. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + */ + typedef typename GenericGL3D::TextureOffset TextureOffset; + + enum: UnsignedInt { + /** + * Color shader output. @ref shaders-generic "Generic output", + * present always. Expects three- or four-component floating-point + * or normalized buffer attachment. + * @m_since{2019,10} + */ + ColorOutput = GenericGL3D::ColorOutput, + + #ifndef MAGNUM_TARGET_GLES2 + /** + * Object ID shader output. @ref shaders-generic "Generic output", + * present only if @ref Flag::ObjectId is set. Expects a + * single-component unsigned integral attachment. Writes the value + * set in @ref setObjectId() there, see + * @ref Shaders-PhongGL-object-id for more information. + * @requires_gl30 Extension @gl_extension{EXT,texture_integer} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL + * 1.0. + * @m_since{2019,10} + */ + ObjectIdOutput = GenericGL3D::ObjectIdOutput + #endif + }; + + /** + * @brief Flag + * + * @see @ref Flags, @ref flags() + */ + enum class Flag: UnsignedShort { + /** + * Multiply ambient color with a texture. + * @see @ref setAmbientColor(), @ref bindAmbientTexture() + */ + AmbientTexture = 1 << 0, + + /** + * Multiply diffuse color with a texture. + * @see @ref setDiffuseColor(), @ref bindDiffuseTexture() + */ + DiffuseTexture = 1 << 1, + + /** + * Multiply specular color with a texture. + * @see @ref setSpecularColor(), @ref bindSpecularTexture() + */ + SpecularTexture = 1 << 2, + + /** + * Modify normals according to a texture. Requires the + * @ref Tangent attribute to be present. + * @m_since{2019,10} + */ + NormalTexture = 1 << 4, + + /** + * Enable alpha masking. If the combined fragment color has an + * alpha less than the value specified with @ref setAlphaMask(), + * given fragment is discarded. + * + * This uses the @glsl discard @ce operation which is known to have + * considerable performance impact on some platforms. While useful + * for cheap alpha masking that doesn't require depth sorting, + * with proper depth sorting and blending you'll usually get much + * better performance and output quality. + */ + AlphaMask = 1 << 3, + + /** + * Multiply diffuse color with a vertex color. Requires either + * the @ref Color3 or @ref Color4 attribute to be present. + * @m_since{2019,10} + */ + VertexColor = 1 << 5, + + /** + * Use the separate @ref Bitangent attribute for retrieving vertex + * bitangents. If this flag is not present, the last component of + * @ref Tangent4 is used to calculate bitangent direction. See + * @ref Shaders-PhongGL-normal-mapping for more information. + * @m_since_latest + */ + Bitangent = 1 << 11, + + /** + * Enable texture coordinate transformation. If this flag is set, + * the shader expects that at least one of + * @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture, + * @ref Flag::SpecularTexture or @ref Flag::NormalTexture is + * enabled as well. + * @see @ref setTextureMatrix() + * @m_since{2020,06} + */ + TextureTransformation = 1 << 6, + + #ifndef MAGNUM_TARGET_GLES2 + /** + * Enable object ID output. See @ref Shaders-PhongGL-object-id + * for more information. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL + * 1.0. + * @m_since{2019,10} + */ + ObjectId = 1 << 7, + + /** + * Instanced object ID. Retrieves a per-instance / per-vertex + * object ID from the @ref ObjectId attribute, outputting a sum of + * the per-vertex ID and ID coming from @ref setObjectId(). + * Implicitly enables @ref Flag::ObjectId. See + * @ref Shaders-PhongGL-object-id for more information. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL + * 1.0. + * @m_since{2020,06} + */ + InstancedObjectId = (1 << 8)|ObjectId, + #endif + + /** + * Instanced transformation. Retrieves a per-instance + * transformation and normal matrix from the + * @ref TransformationMatrix / @ref NormalMatrix attributes and + * uses them together with matrices coming from + * @ref setTransformationMatrix() and @ref setNormalMatrix() (first + * the per-instance, then the uniform matrix). See + * @ref Shaders-PhongGL-instancing for more information. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + * @m_since{2020,06} + */ + InstancedTransformation = 1 << 9, + + /** + * Instanced texture offset. Retrieves a per-instance offset vector + * from the @ref TextureOffset attribute and uses it together with + * the matrix coming from @ref setTextureMatrix() (first the + * per-instance vector, then the uniform matrix). Instanced texture + * scaling and rotation is not supported at the moment, you can + * specify that only via the uniform @ref setTextureMatrix(). + * Implicitly enables @ref Flag::TextureTransformation. See + * @ref Shaders-PhongGL-instancing for more information. + * @requires_gl33 Extension @gl_extension{ARB,instanced_arrays} + * @requires_gles30 Extension @gl_extension{ANGLE,instanced_arrays}, + * @gl_extension{EXT,instanced_arrays} or + * @gl_extension{NV,instanced_arrays} in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} + * in WebGL 1.0. + * @m_since{2020,06} + */ + InstancedTextureOffset = (1 << 10)|TextureTransformation + }; + + /** + * @brief Flags + * + * @see @ref flags() + */ + typedef Containers::EnumSet Flags; + + /** + * @brief Constructor + * @param flags Flags + * @param lightCount Count of light sources + */ + explicit PhongGL(Flags flags = {}, UnsignedInt lightCount = 1); + + /** + * @brief Construct without creating the underlying OpenGL object + * + * The constructed instance is equivalent to a moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit PhongGL(NoCreateT) noexcept: GL::AbstractShaderProgram{NoCreate} {} + + /** @brief Copying is not allowed */ + PhongGL(const PhongGL&) = delete; + + /** @brief Move constructor */ + PhongGL(PhongGL&&) noexcept = default; + + /** @brief Copying is not allowed */ + PhongGL& operator=(const PhongGL&) = delete; + + /** @brief Move assignment */ + PhongGL& operator=(PhongGL&&) noexcept = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** @brief Light count */ + UnsignedInt lightCount() const { return _lightCount; } + + /** + * @brief Set ambient color + * @return Reference to self (for method chaining) + * + * If @ref Flag::AmbientTexture is set, default value is + * @cpp 0xffffffff_rgbaf @ce and the color will be multiplied with + * ambient texture, otherwise default value is @cpp 0x00000000_rgbaf @ce. + * @see @ref bindAmbientTexture(), @ref Shaders-PhongGL-lights-ambient + */ + PhongGL& setAmbientColor(const Magnum::Color4& color); + + /** + * @brief Bind an ambient texture + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::AmbientTexture + * enabled. + * @see @ref bindTextures(), @ref setAmbientColor(), + * @ref Shaders-PhongGL-lights-ambient + */ + PhongGL& bindAmbientTexture(GL::Texture2D& texture); + + /** + * @brief Set diffuse color + * @return Reference to self (for method chaining) + * + * Initial value is @cpp 0xffffffff_rgbaf @ce. If @ref lightCount() is + * zero, this function is a no-op, as diffuse color doesn't contribute + * to the output in that case. + * @see @ref bindDiffuseTexture() + */ + PhongGL& setDiffuseColor(const Magnum::Color4& color); + + /** + * @brief Bind a diffuse texture + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::DiffuseTexture + * enabled. If @ref lightCount() is zero, this function is a no-op, as + * diffuse color doesn't contribute to the output in that case. + * @see @ref bindTextures(), @ref setDiffuseColor() + */ + PhongGL& bindDiffuseTexture(GL::Texture2D& texture); + + /** + * @brief Set normal texture scale + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Affects strength of the normal mapping. Initial value is + * @cpp 1.0f @ce, meaning the normal texture is not changed in any way; + * a value of @cpp 0.0f @ce disables the normal texture effect + * altogether. + * + * Expects that the shader was created with @ref Flag::NormalTexture + * enabled. If @ref lightCount() is zero, this function is a no-op, as + * normals don't contribute to the output in that case. + * @see @ref Shaders-PhongGL-normal-mapping, @ref bindNormalTexture(), + * @ref Trade::MaterialAttribute::NormalTextureScale + */ + PhongGL& setNormalTextureScale(Float scale); + + /** + * @brief Bind a normal texture + * @return Reference to self (for method chaining) + * @m_since{2019,10} + * + * Expects that the shader was created with @ref Flag::NormalTexture + * enabled and the @ref Tangent attribute was supplied. If + * @ref lightCount() is zero, this function is a no-op, as normals + * don't contribute to the output in that case. + * @see @ref Shaders-PhongGL-normal-mapping, + * @ref bindTextures(), @ref setNormalTextureScale() + */ + PhongGL& bindNormalTexture(GL::Texture2D& texture); + + /** + * @brief Set specular color + * @return Reference to self (for method chaining) + * + * Initial value is @cpp 0xffffff00_rgbaf @ce. Color will be multiplied + * with specular texture if @ref Flag::SpecularTexture is set. If you + * want to have a fully diffuse material, set specular color to + * @cpp 0x00000000_rgbaf @ce. If @ref lightCount() is zero, this + * function is a no-op, as specular color doesn't contribute to the + * output in that case. + * @see @ref bindSpecularTexture() + */ + PhongGL& setSpecularColor(const Magnum::Color4& color); + + /** + * @brief Bind a specular texture + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::SpecularTexture + * enabled. If @ref lightCount() is zero, this function is a no-op, as + * specular color doesn't contribute to the output in that case. + * @see @ref bindTextures(), @ref setSpecularColor() + */ + PhongGL& bindSpecularTexture(GL::Texture2D& texture); + + /** + * @brief Bind textures + * @return Reference to self (for method chaining) + * + * A particular texture has effect only if particular texture flag from + * @ref PhongGL::Flag "Flag" is set, you can use @cpp nullptr @ce for + * the rest. Expects that the shader was created with at least one of + * @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture, + * @ref Flag::SpecularTexture or @ref Flag::NormalTexture enabled. More + * efficient than setting each texture separately. + * @see @ref bindAmbientTexture(), @ref bindDiffuseTexture(), + * @ref bindSpecularTexture(), @ref bindNormalTexture() + */ + PhongGL& bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal + #ifdef MAGNUM_BUILD_DEPRECATED + = nullptr + #endif + ); + + /** + * @brief Set shininess + * @return Reference to self (for method chaining) + * + * The larger value, the harder surface (smaller specular highlight). + * Initial value is @cpp 80.0f @ce. If @ref lightCount() is zero, this + * function is a no-op, as specular color doesn't contribute to the + * output in that case. + */ + PhongGL& setShininess(Float shininess); + + /** + * @brief Set alpha mask value + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::AlphaMask + * enabled. Fragments with alpha values smaller than the mask value + * will be discarded. Initial value is @cpp 0.5f @ce. See the flag + * documentation for further information. + * + * This corresponds to @m_class{m-doc-external} [glAlphaFunc()](https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glAlphaFunc.xml) + * in classic OpenGL. + * @m_keywords{glAlphaFunc()} + */ + PhongGL& setAlphaMask(Float mask); + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Set object ID + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::ObjectId + * enabled. Value set here is written to the @ref ObjectIdOutput, see + * @ref Shaders-PhongGL-object-id for more information. Default is + * @cpp 0 @ce. + * @requires_gl30 Extension @gl_extension{EXT,gpu_shader4} + * @requires_gles30 Object ID output requires integer support in + * shaders, which is not available in OpenGL ES 2.0 or WebGL 1.0. + */ + PhongGL& setObjectId(UnsignedInt id); + #endif + + /** + * @brief Set transformation matrix + * @return Reference to self (for method chaining) + * + * You need to set also @ref setNormalMatrix() with a corresponding + * value. Initial value is an identity matrix. + */ + PhongGL& setTransformationMatrix(const Matrix4& matrix); + + /** + * @brief Set normal matrix + * @return Reference to self (for method chaining) + * + * The matrix doesn't need to be normalized, as renormalization is done + * per-fragment anyway. You need to set also + * @ref setTransformationMatrix() with a corresponding value. Initial + * value is an identity matrix. If @ref lightCount() is zero, this + * function is a no-op, as normals don't contribute to the output in + * that case. + * @see @ref Math::Matrix4::normalMatrix() + */ + PhongGL& setNormalMatrix(const Matrix3x3& matrix); + + /** + * @brief Set projection matrix + * @return Reference to self (for method chaining) + * + * Initial value is an identity matrix (i.e., an orthographic + * projection of the default @f$ [ -\boldsymbol{1} ; \boldsymbol{1} ] @f$ + * cube). + */ + PhongGL& setProjectionMatrix(const Matrix4& matrix); + + /** + * @brief Set texture coordinate transformation matrix + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * Expects that the shader was created with + * @ref Flag::TextureTransformation enabled. Initial value is an + * identity matrix. + */ + PhongGL& setTextureMatrix(const Matrix3& matrix); + + /** + * @brief Set light positions + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Depending on the fourth component, the value is treated as either a + *camera-relative position of a point light, if the fourth component is + * @cpp 1.0f @ce; or a direction *to* a directional light, if the + * fourth component is @cpp 0.0f @ce. Expects that the size of the + * @p positions array is the same as @ref lightCount(). Initial values + * are @cpp {0.0f, 0.0f, 1.0f, 0.0f} @ce --- a directional "fill" light + * coming from the camera. + * @see @ref Shaders-PhongGL-lights, @ref setLightPosition() + */ + PhongGL& setLightPositions(Containers::ArrayView positions); + + /** + * @overload + * @m_since_latest + */ + PhongGL& setLightPositions(std::initializer_list positions); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief setLightPositions(Containers::ArrayView) + * @m_deprecated_since_latest Use @ref setLightPositions(Containers::ArrayView) + * instead. This function sets the fourth component to + * @cpp 0.0f @ce to preserve the original behavior as close as + * possible. + */ + CORRADE_DEPRECATED("use setLightPositions(Containers::ArrayView) instead") PhongGL& setLightPositions(Containers::ArrayView positions); + + /** + * @brief @copybrief setLightPositions(std::initializer_list) + * @m_deprecated_since_latest Use @ref setLightPositions(std::initializer_list) + * instead. This function sets the fourth component to + * @cpp 0.0f @ce to preserve the original behavior as close as + * possible. + */ + CORRADE_DEPRECATED("use setLightPositions(std::initializer_list) instead") PhongGL& setLightPositions(std::initializer_list positions); + #endif + + /** + * @brief Set position for given light + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setLightPositions() updates just a single light + * position. If updating more than one light, prefer the batch function + * instead to reduce the count of GL API calls. Expects that @p id is + * less than @ref lightCount(). + */ + PhongGL& setLightPosition(UnsignedInt id, const Vector4& position); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief setLightPosition(UnsignedInt, const Vector4&) + * @m_deprecated_since_latest Use @ref setLightPosition(UnsignedInt, const Vector4&) + * instead. This function sets the fourth component to + * @cpp 0.0f @ce to preserve the original behavior as close as + * possible. + */ + CORRADE_DEPRECATED("use setLightPosition(UnsignedInt, const Vector4&) instead") PhongGL& setLightPosition(UnsignedInt id, const Vector3& position); + + /** + * @brief Set light position + * @m_deprecated_since_latest Use @ref setLightPositions(std::initializer_list) + * with a single item instead --- it's short enough to not warrant + * the existence of a dedicated overload. This function sets the + * fourth component to @cpp 0.0f @ce to preserve the original + * behavior as close as possible. + */ + CORRADE_DEPRECATED("use setLightPositions(std::initializer_list) instead") PhongGL& setLightPosition(const Vector3& position); + #endif + + /** + * @brief Set light colors + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Initial values are @cpp 0xffffff_rgbf @ce. Expects that the size + * of the @p colors array is the same as @ref lightCount(). + * @see @ref Shaders-PhongGL-lights, @ref setLightColor() + */ + PhongGL& setLightColors(Containers::ArrayView colors); + + /** + * @overload + * @m_since_latest + */ + PhongGL& setLightColors(std::initializer_list colors); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief setLightColors(Containers::ArrayView) + * @m_deprecated_since_latest Use @ref setLightColors(Containers::ArrayView) + * instead. The alpha channel isn't used in any way. + */ + CORRADE_DEPRECATED("use setLightColors(Containers::ArrayView) instead") PhongGL& setLightColors(Containers::ArrayView colors); + + /** + * @brief @copybrief setLightColors(std::initializer_list) + * @m_deprecated_since_latest Use @ref setLightColors(std::initializer_list) + * instead. The alpha channel isn't used in any way. + */ + CORRADE_DEPRECATED("use setLightColors(std::initializer_list) instead") PhongGL& setLightColors(std::initializer_list colors); + #endif + + /** + * @brief Set color for given light + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setLightColors() updates just a single light color. If + * updating more than one light, prefer the batch function instead to + * reduce the count of GL API calls. Expects that @p id is less than + * @ref lightCount(). + */ + PhongGL& setLightColor(UnsignedInt id, const Magnum::Color3& color); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief @copybrief setLightColor(UnsignedInt, const Magnum::Color3&) + * @m_deprecated_since_latest Use @ref setLightColor(UnsignedInt, const Magnum::Color3&) + * instead. The alpha channel isn't used in any way. + */ + CORRADE_DEPRECATED("use setLightColor(UnsignedInt, const Magnum::Color3&) instead") PhongGL& setLightColor(UnsignedInt id, const Magnum::Color4& color); + + /** + * @brief Set light color + * @m_deprecated_since_latest Use @ref setLightColors(std::initializer_list) + * with a single item instead --- it's short enough to not warrant + * the existence of a dedicated overload. The alpha channel isn't + * used in any way. + */ + CORRADE_DEPRECATED("use setLightColor(std::initializer_list) instead") PhongGL& setLightColor(const Magnum::Color4& color); + #endif + + /** + * @brief Set light specular colors + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Usually you'd set this value to the same as @ref setLightColors(), + * but it allows for greater flexibility such as disabling specular + * highlights on certain lights. Initial values are + * @cpp 0xffffff_rgbf @ce. Expects that the size of the @p colors array + * is the same as @ref lightCount(). + * @see @ref Shaders-PhongGL-lights, @ref setLightColor() + */ + PhongGL& setLightSpecularColors(Containers::ArrayView colors); + + /** + * @overload + * @m_since_latest + */ + PhongGL& setLightSpecularColors(std::initializer_list colors); + + /** + * @brief Set specular color for given light + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setLightSpecularColors() updates just a single light + * color. If updating more than one light, prefer the batch function + * instead to reduce the count of GL API calls. Expects that @p id is + * less than @ref lightCount(). + */ + PhongGL& setLightSpecularColor(UnsignedInt id, const Magnum::Color3& color); + + /** + * @brief Set light attenuation ranges + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Initial values are @ref Constants::inf(). Expects that the size of + * the @p ranges array is the same as @ref lightCount(). + * @see @ref Shaders-PhongGL-lights, @ref setLightRange() + */ + PhongGL& setLightRanges(Containers::ArrayView ranges); + + /** + * @overload + * @m_since_latest + */ + PhongGL& setLightRanges(std::initializer_list ranges); + + /** + * @brief Set attenuation range for given light + * @return Reference to self (for method chaining) + * @m_since_latest + * + * Unlike @ref setLightRanges() updates just a single light range. If + * updating more than one light, prefer the batch function instead to + * reduce the count of GL API calls. Expects that @p id is less than + * @ref lightCount(). + */ + PhongGL& setLightRange(UnsignedInt id, Float range); + + private: + /* Prevent accidentally calling irrelevant functions */ + #ifndef MAGNUM_TARGET_GLES + using GL::AbstractShaderProgram::drawTransformFeedback; + #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + using GL::AbstractShaderProgram::dispatchCompute; + #endif + + Flags _flags; + UnsignedInt _lightCount{}; + Int _transformationMatrixUniform{0}, + _projectionMatrixUniform{1}, + _normalMatrixUniform{2}, + _textureMatrixUniform{3}, + _ambientColorUniform{4}, + _diffuseColorUniform{5}, + _specularColorUniform{6}, + _shininessUniform{7}, + _normalTextureScaleUniform{8}, + _alphaMaskUniform{9}; + #ifndef MAGNUM_TARGET_GLES2 + Int _objectIdUniform{10}; + #endif + Int _lightPositionsUniform{11}, + _lightColorsUniform, /* 11 + lightCount, set in the constructor */ + _lightSpecularColorsUniform, /* 11 + 2*lightCount */ + _lightRangesUniform; /* 11 + 3*lightCount */ +}; + +/** @debugoperatorclassenum{PhongGL,PhongGL::Flag} */ +MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, PhongGL::Flag value); + +/** @debugoperatorclassenum{PhongGL,PhongGL::Flags} */ +MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, PhongGL::Flags value); + +CORRADE_ENUMSET_OPERATORS(PhongGL::Flags) + +}} + +#endif diff --git a/src/Magnum/Shaders/Shaders.h b/src/Magnum/Shaders/Shaders.h index d5d556bce..5e353add8 100644 --- a/src/Magnum/Shaders/Shaders.h +++ b/src/Magnum/Shaders/Shaders.h @@ -38,35 +38,65 @@ namespace Magnum { namespace Shaders { #ifndef DOXYGEN_GENERATING_OUTPUT -template class DistanceFieldVector; -typedef DistanceFieldVector<2> DistanceFieldVector2D; -typedef DistanceFieldVector<3> DistanceFieldVector3D; +template class AbstractVectorGL; +typedef AbstractVectorGL<2> AbstractVectorGL2D; +typedef AbstractVectorGL<3> AbstractVectorGL3D; +#ifdef MAGNUM_BUILD_DEPRECATED +template using AbstractVector CORRADE_DEPRECATED_ALIAS("use AbstractVectorGL instead") = AbstractVectorGL; +typedef CORRADE_DEPRECATED("use AbstractVectorGL2D instead") AbstractVectorGL2D AbstractVector2D; +typedef CORRADE_DEPRECATED("use AbstractVectorGL3D instead") AbstractVectorGL3D AbstractVector3D; +#endif -template class AbstractVector; -typedef AbstractVector<2> AbstractVector2D; -typedef AbstractVector<3> AbstractVector3D; +template class DistanceFieldVectorGL; +typedef DistanceFieldVectorGL<2> DistanceFieldVectorGL2D; +typedef DistanceFieldVectorGL<3> DistanceFieldVectorGL3D; +#ifdef MAGNUM_BUILD_DEPRECATED +template using DistanceFieldVector CORRADE_DEPRECATED_ALIAS("use DistanceFieldVectorGL instead") = DistanceFieldVectorGL; +typedef CORRADE_DEPRECATED("use DistanceFieldVectorGL2D instead") DistanceFieldVectorGL2D DistanceFieldVector2D; +typedef CORRADE_DEPRECATED("use DistanceFieldVectorGL3D instead") DistanceFieldVectorGL3D DistanceFieldVector3D; +#endif -template class Flat; -typedef Flat<2> Flat2D; -typedef Flat<3> Flat3D; +template class FlatGL; +typedef FlatGL<2> FlatGL2D; +typedef FlatGL<3> FlatGL3D; +#ifdef MAGNUM_BUILD_DEPRECATED +template using Flat CORRADE_DEPRECATED_ALIAS("use FlatGL instead") = FlatGL; +typedef CORRADE_DEPRECATED("use FlatGL2D instead") FlatGL2D Flat2D; +typedef CORRADE_DEPRECATED("use FlatGL3D instead") FlatGL3D Flat3D; +#endif /* Generic is used only statically */ -class MeshVisualizer2D; -class MeshVisualizer3D; +class MeshVisualizerGL2D; +class MeshVisualizerGL3D; #ifdef MAGNUM_BUILD_DEPRECATED -typedef CORRADE_DEPRECATED("use MeshVisualizer3D instead") MeshVisualizer3D MeshVisualizer; +typedef CORRADE_DEPRECATED("use MeshVisualizerGL2D instead") MeshVisualizerGL2D MeshVisualizer2D; +typedef CORRADE_DEPRECATED("use MeshVisualizerGL3D instead") MeshVisualizerGL3D MeshVisualizer3D; +typedef CORRADE_DEPRECATED("use MeshVisualizerGL3D instead") MeshVisualizerGL3D MeshVisualizer; #endif -class Phong; +class PhongGL; +#ifdef MAGNUM_BUILD_DEPRECATED +typedef CORRADE_DEPRECATED("use PhongGL instead") PhongGL Phong; +#endif -template class Vector; -typedef Vector<2> Vector2D; -typedef Vector<3> Vector3D; +template class VectorGL; +typedef VectorGL<2> VectorGL2D; +typedef VectorGL<3> VectorGL3D; +#ifdef MAGNUM_BUILD_DEPRECATED +template using Vector CORRADE_DEPRECATED_ALIAS("use VectorGL instead") = VectorGL; +typedef CORRADE_DEPRECATED("use VectorGL2D instead") VectorGL2D Vector2D; +typedef CORRADE_DEPRECATED("use VectorGL3D instead") VectorGL3D Vector3D; +#endif -template class VertexColor; -typedef VertexColor<2> VertexColor2D; -typedef VertexColor<3> VertexColor3D; +template class VertexColorGL; +typedef VertexColorGL<2> VertexColorGL2D; +typedef VertexColorGL<3> VertexColorGL3D; +#ifdef MAGNUM_BUILD_DEPRECATED +template using VertexColor CORRADE_DEPRECATED_ALIAS("use VertexColorGL instead") = VertexColorGL; +typedef CORRADE_DEPRECATED("use VertexColorGL2D instead") VertexColorGL2D VertexColor2D; +typedef CORRADE_DEPRECATED("use VertexColorGL3D instead") VertexColorGL3D VertexColor3D; +#endif #endif }} diff --git a/src/Magnum/Shaders/Test/CMakeLists.txt b/src/Magnum/Shaders/Test/CMakeLists.txt index f2cb31c5c..5e90c28f9 100644 --- a/src/Magnum/Shaders/Test/CMakeLists.txt +++ b/src/Magnum/Shaders/Test/CMakeLists.txt @@ -23,21 +23,23 @@ # DEALINGS IN THE SOFTWARE. # -corrade_add_test(ShadersDistanceFieldVectorTest DistanceFieldVectorTest.cpp LIBRARIES MagnumShaders) -corrade_add_test(ShadersFlatTest FlatTest.cpp LIBRARIES MagnumShaders) -corrade_add_test(ShadersGenericTest GenericTest.cpp LIBRARIES MagnumShaders) -corrade_add_test(ShadersMeshVisualizerTest MeshVisualizerTest.cpp LIBRARIES MagnumShaders) -corrade_add_test(ShadersPhongTest PhongTest.cpp LIBRARIES MagnumShaders) -corrade_add_test(ShadersVectorTest VectorTest.cpp LIBRARIES MagnumShaders) -corrade_add_test(ShadersVertexColorTest VertexColorTest.cpp LIBRARIES MagnumShaders) +# There's an underscore between GL and Test to disambiguate from GLTest, which +# is a common suffix used to mark tests that need a GL context. Ugly, I know. +corrade_add_test(ShadersDistanceFieldVectorGL_Test DistanceFieldVectorGL_Test.cpp LIBRARIES MagnumShaders) +corrade_add_test(ShadersFlatGL_Test FlatGL_Test.cpp LIBRARIES MagnumShaders) +corrade_add_test(ShadersGenericGL_Test GenericGL_Test.cpp LIBRARIES MagnumShaders) +corrade_add_test(ShadersMeshVisualizerGL_Test MeshVisualizerGL_Test.cpp LIBRARIES MagnumShaders) +corrade_add_test(ShadersPhongGL_Test PhongGL_Test.cpp LIBRARIES MagnumShaders) +corrade_add_test(ShadersVectorGL_Test VectorGL_Test.cpp LIBRARIES MagnumShaders) +corrade_add_test(ShadersVertexColorGL_Test VertexColorGL_Test.cpp LIBRARIES MagnumShaders) set_target_properties( - ShadersDistanceFieldVectorTest - ShadersFlatTest - ShadersMeshVisualizerTest - ShadersPhongTest - ShadersVectorTest - ShadersVertexColorTest + ShadersDistanceFieldVectorGL_Test + ShadersFlatGL_Test + ShadersMeshVisualizerGL_Test + ShadersPhongGL_Test + ShadersVectorGL_Test + ShadersVertexColorGL_Test PROPERTIES FOLDER "Magnum/Shaders/Test") if(BUILD_GL_TESTS) diff --git a/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp b/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp index 117bc45a6..e9aeaee0a 100644 --- a/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp +++ b/src/Magnum/Shaders/Test/DistanceFieldVectorGLTest.cpp @@ -47,7 +47,7 @@ #include "Magnum/MeshTools/Compile.h" #include "Magnum/Primitives/Plane.h" #include "Magnum/Primitives/Square.h" -#include "Magnum/Shaders/DistanceFieldVector.h" +#include "Magnum/Shaders/DistanceFieldVectorGL.h" #include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/ImageData.h" #include "Magnum/Trade/MeshData.h" @@ -99,15 +99,15 @@ using namespace Math::Literals; constexpr struct { const char* name; - DistanceFieldVector2D::Flags flags; + DistanceFieldVectorGL2D::Flags flags; } ConstructData[]{ {"", {}}, - {"texture transformation", DistanceFieldVector2D::Flag::TextureTransformation} + {"texture transformation", DistanceFieldVectorGL2D::Flag::TextureTransformation} }; const struct { const char* name; - DistanceFieldVector2D::Flags flags; + DistanceFieldVectorGL2D::Flags flags; Matrix3 textureTransformation; Color4 color, outlineColor; Float outlineRangeStart, outlineRangeEnd, smoothness; @@ -115,7 +115,7 @@ const struct { const char* file3D; bool flip; } RenderData[] { - {"texture transformation", DistanceFieldVector2D::Flag::TextureTransformation, + {"texture transformation", DistanceFieldVectorGL2D::Flag::TextureTransformation, Matrix3::translation(Vector2{1.0f})*Matrix3::scaling(Vector2{-1.0f}), 0xffffff_rgbf, 0x00000000_rgbaf, 0.5f, 1.0f, 0.04f, "defaults-distancefield.tga", "defaults-distancefield.tga", true}, @@ -181,7 +181,7 @@ template void DistanceFieldVectorGLTest::construct() { auto&& data = ConstructData[testCaseInstanceId()]; setTestCaseDescription(data.name); - DistanceFieldVector shader{data.flags}; + DistanceFieldVectorGL shader{data.flags}; CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_VERIFY(shader.id()); { @@ -197,21 +197,21 @@ template void DistanceFieldVectorGLTest::construct() { template void DistanceFieldVectorGLTest::constructMove() { setTestCaseTemplateName(std::to_string(dimensions)); - DistanceFieldVector a{DistanceFieldVector::Flag::TextureTransformation}; + DistanceFieldVectorGL a{DistanceFieldVectorGL::Flag::TextureTransformation}; const GLuint id = a.id(); CORRADE_VERIFY(id); MAGNUM_VERIFY_NO_GL_ERROR(); - DistanceFieldVector b{std::move(a)}; + DistanceFieldVectorGL b{std::move(a)}; CORRADE_COMPARE(b.id(), id); - CORRADE_COMPARE(b.flags(), DistanceFieldVector::Flag::TextureTransformation); + CORRADE_COMPARE(b.flags(), DistanceFieldVectorGL::Flag::TextureTransformation); CORRADE_VERIFY(!a.id()); - DistanceFieldVector c{NoCreate}; + DistanceFieldVectorGL c{NoCreate}; c = std::move(b); CORRADE_COMPARE(c.id(), id); - CORRADE_COMPARE(c.flags(), DistanceFieldVector::Flag::TextureTransformation); + CORRADE_COMPARE(c.flags(), DistanceFieldVectorGL::Flag::TextureTransformation); CORRADE_VERIFY(!b.id()); } @@ -225,11 +225,11 @@ template void DistanceFieldVectorGLTest::setTextureMatri std::ostringstream out; Error redirectError{&out}; - DistanceFieldVector shader; + DistanceFieldVectorGL shader; shader.setTextureMatrix({}); CORRADE_COMPARE(out.str(), - "Shaders::DistanceFieldVector::setTextureMatrix(): the shader was not created with texture transformation enabled\n"); + "Shaders::DistanceFieldVectorGL::setTextureMatrix(): the shader was not created with texture transformation enabled\n"); } constexpr Vector2i RenderSize{80, 80}; @@ -293,7 +293,7 @@ void DistanceFieldVectorGLTest::renderDefaults2D() { .setSubImage(0, {}, *image); #endif - DistanceFieldVector2D{} + DistanceFieldVectorGL2D{} .bindVectorTexture(texture) .draw(square); @@ -349,7 +349,7 @@ void DistanceFieldVectorGLTest::renderDefaults3D() { .setSubImage(0, {}, *image); #endif - DistanceFieldVector2D{} + DistanceFieldVectorGL2D{} .bindVectorTexture(texture) .draw(plane); @@ -408,7 +408,7 @@ void DistanceFieldVectorGLTest::render2D() { .setSubImage(0, {}, *image); #endif - DistanceFieldVector2D shader{data.flags}; + DistanceFieldVectorGL2D shader{data.flags}; shader /** @todo implement background color */ .setColor(data.color) @@ -474,7 +474,7 @@ void DistanceFieldVectorGLTest::render3D() { .setSubImage(0, {}, *image); #endif - DistanceFieldVector3D shader{data.flags}; + DistanceFieldVectorGL3D shader{data.flags}; shader /** @todo implement background color */ .setColor(data.color) diff --git a/src/Magnum/Shaders/Test/DistanceFieldVectorTest.cpp b/src/Magnum/Shaders/Test/DistanceFieldVectorGL_Test.cpp similarity index 51% rename from src/Magnum/Shaders/Test/DistanceFieldVectorTest.cpp rename to src/Magnum/Shaders/Test/DistanceFieldVectorGL_Test.cpp index 285f6dc63..b337b24c5 100644 --- a/src/Magnum/Shaders/Test/DistanceFieldVectorTest.cpp +++ b/src/Magnum/Shaders/Test/DistanceFieldVectorGL_Test.cpp @@ -27,12 +27,14 @@ #include #include -#include "Magnum/Shaders/DistanceFieldVector.h" +#include "Magnum/Shaders/DistanceFieldVectorGL.h" namespace Magnum { namespace Shaders { namespace Test { namespace { -struct DistanceFieldVectorTest: TestSuite::Tester { - explicit DistanceFieldVectorTest(); +/* There's an underscore between GL and Test to disambiguate from GLTest, which + is a common suffix used to mark tests that need a GL context. Ugly, I know. */ +struct DistanceFieldVectorGL_Test: TestSuite::Tester { + explicit DistanceFieldVectorGL_Test(); template void constructNoCreate(); template void constructCopy(); @@ -41,50 +43,50 @@ struct DistanceFieldVectorTest: TestSuite::Tester { void debugFlags(); }; -DistanceFieldVectorTest::DistanceFieldVectorTest() { - addTests({&DistanceFieldVectorTest::constructNoCreate<2>, - &DistanceFieldVectorTest::constructNoCreate<3>, +DistanceFieldVectorGL_Test::DistanceFieldVectorGL_Test() { + addTests({&DistanceFieldVectorGL_Test::constructNoCreate<2>, + &DistanceFieldVectorGL_Test::constructNoCreate<3>, - &DistanceFieldVectorTest::constructCopy<2>, - &DistanceFieldVectorTest::constructCopy<3>, + &DistanceFieldVectorGL_Test::constructCopy<2>, + &DistanceFieldVectorGL_Test::constructCopy<3>, - &DistanceFieldVectorTest::debugFlag, - &DistanceFieldVectorTest::debugFlags}); + &DistanceFieldVectorGL_Test::debugFlag, + &DistanceFieldVectorGL_Test::debugFlags}); } -template void DistanceFieldVectorTest::constructNoCreate() { +template void DistanceFieldVectorGL_Test::constructNoCreate() { setTestCaseTemplateName(std::to_string(dimensions)); { - DistanceFieldVector shader{NoCreate}; + DistanceFieldVectorGL shader{NoCreate}; CORRADE_COMPARE(shader.id(), 0); - CORRADE_COMPARE(shader.flags(), typename DistanceFieldVector::Flags{}); + CORRADE_COMPARE(shader.flags(), typename DistanceFieldVectorGL::Flags{}); } CORRADE_VERIFY(true); } -template void DistanceFieldVectorTest::constructCopy() { +template void DistanceFieldVectorGL_Test::constructCopy() { setTestCaseTemplateName(std::to_string(dimensions)); - CORRADE_VERIFY(!std::is_copy_constructible>{}); - CORRADE_VERIFY(!std::is_copy_assignable>{}); + CORRADE_VERIFY(!std::is_copy_constructible>{}); + CORRADE_VERIFY(!std::is_copy_assignable>{}); } -void DistanceFieldVectorTest::debugFlag() { +void DistanceFieldVectorGL_Test::debugFlag() { std::ostringstream out; - Debug{&out} << DistanceFieldVector2D::Flag::TextureTransformation << DistanceFieldVector2D::Flag(0xf0); - CORRADE_COMPARE(out.str(), "Shaders::DistanceFieldVector::Flag::TextureTransformation Shaders::DistanceFieldVector::Flag(0xf0)\n"); + Debug{&out} << DistanceFieldVectorGL2D::Flag::TextureTransformation << DistanceFieldVectorGL2D::Flag(0xf0); + CORRADE_COMPARE(out.str(), "Shaders::DistanceFieldVectorGL::Flag::TextureTransformation Shaders::DistanceFieldVectorGL::Flag(0xf0)\n"); } -void DistanceFieldVectorTest::debugFlags() { +void DistanceFieldVectorGL_Test::debugFlags() { std::ostringstream out; - Debug{&out} << DistanceFieldVector3D::Flags{DistanceFieldVector3D::Flag::TextureTransformation|DistanceFieldVector3D::Flag(0xf0)} << DistanceFieldVector3D::Flags{}; - CORRADE_COMPARE(out.str(), "Shaders::DistanceFieldVector::Flag::TextureTransformation|Shaders::DistanceFieldVector::Flag(0xf0) Shaders::DistanceFieldVector::Flags{}\n"); + Debug{&out} << DistanceFieldVectorGL3D::Flags{DistanceFieldVectorGL3D::Flag::TextureTransformation|DistanceFieldVectorGL3D::Flag(0xf0)} << DistanceFieldVectorGL3D::Flags{}; + CORRADE_COMPARE(out.str(), "Shaders::DistanceFieldVectorGL::Flag::TextureTransformation|Shaders::DistanceFieldVectorGL::Flag(0xf0) Shaders::DistanceFieldVectorGL::Flags{}\n"); } }}}} -CORRADE_TEST_MAIN(Magnum::Shaders::Test::DistanceFieldVectorTest) +CORRADE_TEST_MAIN(Magnum::Shaders::Test::DistanceFieldVectorGL_Test) diff --git a/src/Magnum/Shaders/Test/FlatGLTest.cpp b/src/Magnum/Shaders/Test/FlatGLTest.cpp index d70caf85b..34f2ff8f2 100644 --- a/src/Magnum/Shaders/Test/FlatGLTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGLTest.cpp @@ -51,7 +51,7 @@ #include "Magnum/MeshTools/Compile.h" #include "Magnum/Primitives/Circle.h" #include "Magnum/Primitives/UVSphere.h" -#include "Magnum/Shaders/Flat.h" +#include "Magnum/Shaders/FlatGL.h" #include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/ImageData.h" #include "Magnum/Trade/MeshData.h" @@ -138,33 +138,33 @@ using namespace Math::Literals; constexpr struct { const char* name; - Flat2D::Flags flags; + FlatGL2D::Flags flags; } ConstructData[]{ {"", {}}, - {"textured", Flat2D::Flag::Textured}, - {"textured + texture transformation", Flat2D::Flag::Textured|Flat2D::Flag::TextureTransformation}, - {"alpha mask", Flat2D::Flag::AlphaMask}, - {"alpha mask + textured", Flat2D::Flag::AlphaMask|Flat2D::Flag::Textured}, - {"vertex colors", Flat2D::Flag::VertexColor}, - {"vertex colors + textured", Flat2D::Flag::VertexColor|Flat2D::Flag::Textured}, + {"textured", FlatGL2D::Flag::Textured}, + {"textured + texture transformation", FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation}, + {"alpha mask", FlatGL2D::Flag::AlphaMask}, + {"alpha mask + textured", FlatGL2D::Flag::AlphaMask|FlatGL2D::Flag::Textured}, + {"vertex colors", FlatGL2D::Flag::VertexColor}, + {"vertex colors + textured", FlatGL2D::Flag::VertexColor|FlatGL2D::Flag::Textured}, #ifndef MAGNUM_TARGET_GLES2 - {"object ID", Flat2D::Flag::ObjectId}, - {"instanced object ID", Flat2D::Flag::InstancedObjectId}, - {"object ID + alpha mask + textured", Flat2D::Flag::ObjectId|Flat2D::Flag::AlphaMask|Flat2D::Flag::Textured}, + {"object ID", FlatGL2D::Flag::ObjectId}, + {"instanced object ID", FlatGL2D::Flag::InstancedObjectId}, + {"object ID + alpha mask + textured", FlatGL2D::Flag::ObjectId|FlatGL2D::Flag::AlphaMask|FlatGL2D::Flag::Textured}, #endif - {"instanced transformation", Flat2D::Flag::InstancedTransformation}, - {"instanced texture offset", Flat2D::Flag::Textured|Flat2D::Flag::InstancedTextureOffset} + {"instanced transformation", FlatGL2D::Flag::InstancedTransformation}, + {"instanced texture offset", FlatGL2D::Flag::Textured|FlatGL2D::Flag::InstancedTextureOffset} }; const struct { const char* name; - Flat2D::Flags flags; + FlatGL2D::Flags flags; Matrix3 textureTransformation; bool flip; } RenderTexturedData[]{ - {"", Flat2D::Flag::Textured, {}, false}, + {"", FlatGL2D::Flag::Textured, {}, false}, {"texture transformation", - Flat2D::Flag::Textured|Flat2D::Flag::TextureTransformation, + FlatGL2D::Flag::Textured|FlatGL2D::Flag::TextureTransformation, Matrix3::translation(Vector2{1.0f})*Matrix3::scaling(Vector2{-1.0f}), true}, }; @@ -174,37 +174,37 @@ const struct { const char* expected2D; const char* expected3D; bool blending; - Flat2D::Flags flags; + FlatGL2D::Flags flags; Float threshold; } RenderAlphaData[] { /* All those deliberately have a non-white diffuse in order to match the expected data from textured() */ {"none", "FlatTestFiles/textured2D.tga", "FlatTestFiles/textured3D.tga", false, - Flat2D::Flag::Textured, 0.0f}, + FlatGL2D::Flag::Textured, 0.0f}, {"blending", "FlatTestFiles/textured2D-alpha.tga", "FlatTestFiles/textured3D-alpha.tga", true, - Flat2D::Flag::Textured, 0.0f}, + FlatGL2D::Flag::Textured, 0.0f}, {"masking 0.0", "FlatTestFiles/textured2D.tga", "FlatTestFiles/textured3D.tga", false, - Flat2D::Flag::Textured, 0.0f}, + FlatGL2D::Flag::Textured, 0.0f}, {"masking 0.5", "FlatTestFiles/textured2D-alpha-mask0.5.tga", "FlatTestFiles/textured3D-alpha-mask0.5.tga", false, - Flat2D::Flag::Textured|Flat2D::Flag::AlphaMask, 0.5f}, + FlatGL2D::Flag::Textured|FlatGL2D::Flag::AlphaMask, 0.5f}, {"masking 1.0", "TestFiles/alpha-mask1.0.tga", "TestFiles/alpha-mask1.0.tga", false, - Flat2D::Flag::Textured|Flat2D::Flag::AlphaMask, 1.0f} + FlatGL2D::Flag::Textured|FlatGL2D::Flag::AlphaMask, 1.0f} }; #ifndef MAGNUM_TARGET_GLES2 constexpr struct { const char* name; - Flat2D::Flags flags; + FlatGL2D::Flags flags; UnsignedInt uniformId; UnsignedInt instanceCount; UnsignedInt expected; } RenderObjectIdData[] { {"", /* Verify that it can hold 16 bits at least */ - Flat2D::Flag::ObjectId, 48526, 0, 48526}, + FlatGL2D::Flag::ObjectId, 48526, 0, 48526}, {"instanced, first instance", - Flat2D::Flag::InstancedObjectId, 13524, 1, 24526}, + FlatGL2D::Flag::InstancedObjectId, 13524, 1, 24526}, {"instanced, second instance", - Flat2D::Flag::InstancedObjectId, 13524, 2, 62347} + FlatGL2D::Flag::InstancedObjectId, 13524, 2, 62347} }; #endif @@ -305,11 +305,11 @@ template void FlatGLTest::construct() { setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES - if((data.flags & Flat2D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) + if((data.flags & FlatGL2D::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif - Flat shader{data.flags}; + FlatGL shader{data.flags}; CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_VERIFY(shader.id()); { @@ -325,21 +325,21 @@ template void FlatGLTest::construct() { template void FlatGLTest::constructMove() { setTestCaseTemplateName(std::to_string(dimensions)); - Flat a{Flat::Flag::Textured}; + FlatGL a{FlatGL::Flag::Textured}; const GLuint id = a.id(); CORRADE_VERIFY(id); MAGNUM_VERIFY_NO_GL_ERROR(); - Flat b{std::move(a)}; + FlatGL b{std::move(a)}; CORRADE_COMPARE(b.id(), id); - CORRADE_COMPARE(b.flags(), Flat::Flag::Textured); + CORRADE_COMPARE(b.flags(), FlatGL::Flag::Textured); CORRADE_VERIFY(!a.id()); - Flat c{NoCreate}; + FlatGL c{NoCreate}; c = std::move(b); CORRADE_COMPARE(c.id(), id); - CORRADE_COMPARE(c.flags(), Flat::Flag::Textured); + CORRADE_COMPARE(c.flags(), FlatGL::Flag::Textured); CORRADE_VERIFY(!b.id()); } @@ -352,9 +352,9 @@ template void FlatGLTest::constructTextureTransformation std::ostringstream out; Error redirectError{&out}; - Flat{Flat::Flag::TextureTransformation}; + FlatGL{FlatGL::Flag::TextureTransformation}; CORRADE_COMPARE(out.str(), - "Shaders::Flat: texture transformation enabled but the shader is not textured\n"); + "Shaders::FlatGL: texture transformation enabled but the shader is not textured\n"); } template void FlatGLTest::bindTextureNotEnabled() { @@ -368,10 +368,10 @@ template void FlatGLTest::bindTextureNotEnabled() { Error redirectError{&out}; GL::Texture2D texture; - Flat shader; + FlatGL shader; shader.bindTexture(texture); - CORRADE_COMPARE(out.str(), "Shaders::Flat::bindTexture(): the shader was not created with texturing enabled\n"); + CORRADE_COMPARE(out.str(), "Shaders::FlatGL::bindTexture(): the shader was not created with texturing enabled\n"); } template void FlatGLTest::setAlphaMaskNotEnabled() { @@ -384,11 +384,11 @@ template void FlatGLTest::setAlphaMaskNotEnabled() { std::ostringstream out; Error redirectError{&out}; - Flat shader; + FlatGL shader; shader.setAlphaMask(0.75f); CORRADE_COMPARE(out.str(), - "Shaders::Flat::setAlphaMask(): the shader was not created with alpha mask enabled\n"); + "Shaders::FlatGL::setAlphaMask(): the shader was not created with alpha mask enabled\n"); } template void FlatGLTest::setTextureMatrixNotEnabled() { @@ -401,11 +401,11 @@ template void FlatGLTest::setTextureMatrixNotEnabled() { std::ostringstream out; Error redirectError{&out}; - Flat shader; + FlatGL shader; shader.setTextureMatrix({}); CORRADE_COMPARE(out.str(), - "Shaders::Flat::setTextureMatrix(): the shader was not created with texture transformation enabled\n"); + "Shaders::FlatGL::setTextureMatrix(): the shader was not created with texture transformation enabled\n"); } #ifndef MAGNUM_TARGET_GLES2 @@ -419,11 +419,11 @@ template void FlatGLTest::setObjectIdNotEnabled() { std::ostringstream out; Error redirectError{&out}; - Flat shader; + FlatGL shader; shader.setObjectId(33376); CORRADE_COMPARE(out.str(), - "Shaders::Flat::setObjectId(): the shader was not created with object ID enabled\n"); + "Shaders::FlatGL::setObjectId(): the shader was not created with object ID enabled\n"); } #endif @@ -457,7 +457,7 @@ void FlatGLTest::renderTeardown() { void FlatGLTest::renderDefaults2D() { GL::Mesh circle = MeshTools::compile(Primitives::circle2DSolid(32)); - Flat2D{} + FlatGL2D{} .draw(circle); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -477,7 +477,7 @@ void FlatGLTest::renderDefaults2D() { void FlatGLTest::renderDefaults3D() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); - Flat3D{} + FlatGL3D{} .draw(sphere); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -497,7 +497,7 @@ void FlatGLTest::renderDefaults3D() { void FlatGLTest::renderColored2D() { GL::Mesh circle = MeshTools::compile(Primitives::circle2DSolid(32)); - Flat2D{} + FlatGL2D{} .setColor(0x9999ff_rgbf) .setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) .draw(circle); @@ -524,7 +524,7 @@ void FlatGLTest::renderColored2D() { void FlatGLTest::renderColored3D() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); - Flat3D{} + FlatGL3D{} .setColor(0x9999ff_rgbf) .setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* @@ -581,7 +581,7 @@ void FlatGLTest::renderSinglePixelTextured2D() { .setStorage(1, TextureFormatRGBA, Vector2i{1}) .setSubImage(0, {}, diffuseImage); - Flat2D{Flat3D::Flag::Textured} + FlatGL2D{FlatGL3D::Flag::Textured} .setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) .bindTexture(texture) .draw(circle); @@ -619,7 +619,7 @@ void FlatGLTest::renderSinglePixelTextured3D() { .setStorage(1, TextureFormatRGBA, Vector2i{1}) .setSubImage(0, {}, diffuseImage); - Flat3D{Flat3D::Flag::Textured} + FlatGL3D{FlatGL3D::Flag::Textured} .setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* Matrix4::translation(Vector3::zAxis(-2.15f))* @@ -671,7 +671,7 @@ void FlatGLTest::renderTextured2D() { .setStorage(1, TextureFormatRGB, image->size()) .setSubImage(0, {}, *image); - Flat2D shader{data.flags}; + FlatGL2D shader{data.flags}; shader .setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) /* Colorized. Case without a color (where it should be white) is tested @@ -727,7 +727,7 @@ void FlatGLTest::renderTextured3D() { .setStorage(1, TextureFormatRGB, image->size()) .setSubImage(0, {}, *image); - Flat3D shader{data.flags}; + FlatGL3D shader{data.flags}; shader .setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* @@ -782,7 +782,7 @@ template void FlatGLTest::renderVertexColor2D() { GL::Buffer colors; colors.setData(colorData); GL::Mesh circle = MeshTools::compile(circleData); - circle.addVertexBuffer(colors, 0, GL::Attribute{}); + circle.addVertexBuffer(colors, 0, GL::Attribute{}); Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); CORRADE_VERIFY(importer); @@ -796,7 +796,7 @@ template void FlatGLTest::renderVertexColor2D() { .setStorage(1, TextureFormatRGB, image->size()) .setSubImage(0, {}, *image); - Flat2D{Flat2D::Flag::Textured|Flat2D::Flag::VertexColor} + FlatGL2D{FlatGL2D::Flag::Textured|FlatGL2D::Flag::VertexColor} .setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) .setColor(0x9999ff_rgbf) .bindTexture(texture) @@ -836,7 +836,7 @@ template void FlatGLTest::renderVertexColor3D() { GL::Buffer colors; colors.setData(colorData); GL::Mesh sphere = MeshTools::compile(sphereData); - sphere.addVertexBuffer(colors, 0, GL::Attribute{}); + sphere.addVertexBuffer(colors, 0, GL::Attribute{}); Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); CORRADE_VERIFY(importer); @@ -850,7 +850,7 @@ template void FlatGLTest::renderVertexColor3D() { .setStorage(1, TextureFormatRGB, image->size()) .setSubImage(0, {}, *image); - Flat3D{Flat3D::Flag::Textured|Flat3D::Flag::VertexColor} + FlatGL3D{FlatGL3D::Flag::Textured|FlatGL3D::Flag::VertexColor} .setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* Matrix4::translation(Vector3::zAxis(-2.15f))* @@ -915,12 +915,12 @@ void FlatGLTest::renderAlpha2D() { GL::Mesh circle = MeshTools::compile(Primitives::circle2DSolid(32, Primitives::Circle2DFlag::TextureCoordinates)); - Flat2D shader{data.flags}; + FlatGL2D shader{data.flags}; shader.setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) .setColor(0x9999ff_rgbf) .bindTexture(texture); - if(data.flags & Flat3D::Flag::AlphaMask) + if(data.flags & FlatGL3D::Flag::AlphaMask) shader.setAlphaMask(data.threshold); shader.draw(circle); @@ -966,7 +966,7 @@ void FlatGLTest::renderAlpha3D() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32, Primitives::UVSphereFlag::TextureCoordinates)); - Flat3D shader{data.flags}; + FlatGL3D shader{data.flags}; shader.setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* Matrix4::translation(Vector3::zAxis(-2.15f))* @@ -975,7 +975,7 @@ void FlatGLTest::renderAlpha3D() { .setColor(0x9999ff_rgbf) .bindTexture(texture); - if(data.flags & Flat3D::Flag::AlphaMask) + if(data.flags & FlatGL3D::Flag::AlphaMask) shader.setAlphaMask(data.threshold); /* For proper Z order draw back faces first and then front faces */ @@ -1026,8 +1026,8 @@ void FlatGLTest::renderObjectIdSetup() { _objectId.setStorage(GL::RenderbufferFormat::R32UI, RenderSize); _framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{1}, _objectId) .mapForDraw({ - {Flat2D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, - {Flat2D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}} + {FlatGL2D::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, + {FlatGL2D::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}} }) .clearColor(1, Vector4ui{27}); } @@ -1056,9 +1056,9 @@ void FlatGLTest::renderObjectId2D() { .setInstanceCount(data.instanceCount) .addVertexBufferInstanced( GL::Buffer{Containers::arrayView({11002u, 48823u})}, - 1, 0, Flat2D::ObjectId{}); + 1, 0, FlatGL2D::ObjectId{}); - Flat2D{data.flags} + FlatGL2D{data.flags} .setColor(0x9999ff_rgbf) .setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) .setObjectId(data.uniformId) @@ -1114,9 +1114,9 @@ void FlatGLTest::renderObjectId3D() { .setInstanceCount(data.instanceCount) .addVertexBufferInstanced( GL::Buffer{Containers::arrayView({11002u, 48823u})}, - 1, 0, Flat2D::ObjectId{}); + 1, 0, FlatGL2D::ObjectId{}); - Flat3D{data.flags} + FlatGL3D{data.flags} .setColor(0x9999ff_rgbf) .setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* @@ -1202,9 +1202,9 @@ void FlatGLTest::renderInstanced2D() { circle .addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0, - Flat2D::TransformationMatrix{}, - Flat2D::Color3{}, - Flat2D::TextureOffset{}) + FlatGL2D::TransformationMatrix{}, + FlatGL2D::Color3{}, + FlatGL2D::TextureOffset{}) .setInstanceCount(3); Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); @@ -1219,10 +1219,10 @@ void FlatGLTest::renderInstanced2D() { .setStorage(1, TextureFormatRGB, image->size()) .setSubImage(0, {}, *image); - Flat2D{Flat2D::Flag::Textured| - Flat2D::Flag::VertexColor| - Flat2D::Flag::InstancedTransformation| - Flat2D::Flag::InstancedTextureOffset} + FlatGL2D{FlatGL2D::Flag::Textured| + FlatGL2D::Flag::VertexColor| + FlatGL2D::Flag::InstancedTransformation| + FlatGL2D::Flag::InstancedTextureOffset} .setColor(0xffff99_rgbf) .setTransformationProjectionMatrix( Matrix3::projection({2.1f, 2.1f})* @@ -1286,9 +1286,9 @@ void FlatGLTest::renderInstanced3D() { sphere .addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0, - Flat3D::TransformationMatrix{}, - Flat3D::Color3{}, - Flat3D::TextureOffset{}) + FlatGL3D::TransformationMatrix{}, + FlatGL3D::Color3{}, + FlatGL3D::TextureOffset{}) .setInstanceCount(3); Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); @@ -1303,10 +1303,10 @@ void FlatGLTest::renderInstanced3D() { .setStorage(1, TextureFormatRGB, image->size()) .setSubImage(0, {}, *image); - Flat3D{Flat3D::Flag::Textured| - Flat3D::Flag::VertexColor| - Flat3D::Flag::InstancedTransformation| - Flat3D::Flag::InstancedTextureOffset} + FlatGL3D{FlatGL3D::Flag::Textured| + FlatGL3D::Flag::VertexColor| + FlatGL3D::Flag::InstancedTransformation| + FlatGL3D::Flag::InstancedTextureOffset} .setColor(0xffff99_rgbf) .setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* diff --git a/src/Magnum/Shaders/Test/FlatTest.cpp b/src/Magnum/Shaders/Test/FlatGL_Test.cpp similarity index 53% rename from src/Magnum/Shaders/Test/FlatTest.cpp rename to src/Magnum/Shaders/Test/FlatGL_Test.cpp index 481076fe1..566ac3eb3 100644 --- a/src/Magnum/Shaders/Test/FlatTest.cpp +++ b/src/Magnum/Shaders/Test/FlatGL_Test.cpp @@ -27,12 +27,14 @@ #include #include -#include "Magnum/Shaders/Flat.h" +#include "Magnum/Shaders/FlatGL.h" namespace Magnum { namespace Shaders { namespace Test { namespace { -struct FlatTest: TestSuite::Tester { - explicit FlatTest(); +/* There's an underscore between GL and Test to disambiguate from GLTest, which + is a common suffix used to mark tests that need a GL context. Ugly, I know. */ +struct FlatGL_Test: TestSuite::Tester { + explicit FlatGL_Test(); template void constructNoCreate(); template void constructCopy(); @@ -42,69 +44,69 @@ struct FlatTest: TestSuite::Tester { void debugFlagsSupersets(); }; -FlatTest::FlatTest() { - addTests({&FlatTest::constructNoCreate<2>, - &FlatTest::constructNoCreate<3>, +FlatGL_Test::FlatGL_Test() { + addTests({&FlatGL_Test::constructNoCreate<2>, + &FlatGL_Test::constructNoCreate<3>, - &FlatTest::constructCopy<2>, - &FlatTest::constructCopy<3>, + &FlatGL_Test::constructCopy<2>, + &FlatGL_Test::constructCopy<3>, - &FlatTest::debugFlag, - &FlatTest::debugFlags, - &FlatTest::debugFlagsSupersets}); + &FlatGL_Test::debugFlag, + &FlatGL_Test::debugFlags, + &FlatGL_Test::debugFlagsSupersets}); } -template void FlatTest::constructNoCreate() { +template void FlatGL_Test::constructNoCreate() { setTestCaseTemplateName(std::to_string(dimensions)); { - Flat shader{NoCreate}; + FlatGL shader{NoCreate}; CORRADE_COMPARE(shader.id(), 0); - CORRADE_COMPARE(shader.flags(), typename Flat::Flags{}); + CORRADE_COMPARE(shader.flags(), typename FlatGL::Flags{}); } CORRADE_VERIFY(true); } -template void FlatTest::constructCopy() { +template void FlatGL_Test::constructCopy() { setTestCaseTemplateName(std::to_string(dimensions)); - CORRADE_VERIFY(!std::is_copy_constructible>{}); - CORRADE_VERIFY(!std::is_copy_assignable>{}); + CORRADE_VERIFY(!std::is_copy_constructible>{}); + CORRADE_VERIFY(!std::is_copy_assignable>{}); } -void FlatTest::debugFlag() { +void FlatGL_Test::debugFlag() { std::ostringstream out; - Debug{&out} << Flat3D::Flag::Textured << Flat3D::Flag(0xf0); - CORRADE_COMPARE(out.str(), "Shaders::Flat::Flag::Textured Shaders::Flat::Flag(0xf0)\n"); + Debug{&out} << FlatGL3D::Flag::Textured << FlatGL3D::Flag(0xf0); + CORRADE_COMPARE(out.str(), "Shaders::FlatGL::Flag::Textured Shaders::FlatGL::Flag(0xf0)\n"); } -void FlatTest::debugFlags() { +void FlatGL_Test::debugFlags() { std::ostringstream out; - Debug{&out} << (Flat3D::Flag::Textured|Flat3D::Flag::AlphaMask) << Flat3D::Flags{}; - CORRADE_COMPARE(out.str(), "Shaders::Flat::Flag::Textured|Shaders::Flat::Flag::AlphaMask Shaders::Flat::Flags{}\n"); + Debug{&out} << (FlatGL3D::Flag::Textured|FlatGL3D::Flag::AlphaMask) << FlatGL3D::Flags{}; + CORRADE_COMPARE(out.str(), "Shaders::FlatGL::Flag::Textured|Shaders::FlatGL::Flag::AlphaMask Shaders::FlatGL::Flags{}\n"); } -void FlatTest::debugFlagsSupersets() { +void FlatGL_Test::debugFlagsSupersets() { #ifndef MAGNUM_TARGET_GLES2 /* InstancedObjectId is a superset of ObjectId so only one should be printed */ { std::ostringstream out; - Debug{&out} << (Flat3D::Flag::ObjectId|Flat3D::Flag::InstancedObjectId); - CORRADE_COMPARE(out.str(), "Shaders::Flat::Flag::InstancedObjectId\n"); + Debug{&out} << (FlatGL3D::Flag::ObjectId|FlatGL3D::Flag::InstancedObjectId); + CORRADE_COMPARE(out.str(), "Shaders::FlatGL::Flag::InstancedObjectId\n"); } #endif /* InstancedTextureOffset is a superset of TextureTransformation so only one should be printed */ std::ostringstream out; - Debug{&out} << (Flat3D::Flag::InstancedTextureOffset|Flat3D::Flag::TextureTransformation); - CORRADE_COMPARE(out.str(), "Shaders::Flat::Flag::InstancedTextureOffset\n"); + Debug{&out} << (FlatGL3D::Flag::InstancedTextureOffset|FlatGL3D::Flag::TextureTransformation); + CORRADE_COMPARE(out.str(), "Shaders::FlatGL::Flag::InstancedTextureOffset\n"); } }}}} -CORRADE_TEST_MAIN(Magnum::Shaders::Test::FlatTest) +CORRADE_TEST_MAIN(Magnum::Shaders::Test::FlatGL_Test) diff --git a/src/Magnum/Shaders/Test/GenericGL_Test.cpp b/src/Magnum/Shaders/Test/GenericGL_Test.cpp new file mode 100644 index 000000000..991fae075 --- /dev/null +++ b/src/Magnum/Shaders/Test/GenericGL_Test.cpp @@ -0,0 +1,118 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 + +#include "Magnum/Shaders/GenericGL.h" +/* Yes, really */ +#include "Magnum/Shaders/generic.glsl" + +namespace Magnum { namespace Shaders { namespace Test { namespace { + +/* There's an underscore between GL and Test to disambiguate from GLTest, which + is a common suffix used to mark tests that need a GL context. Ugly, I know. */ +struct GenericGL_Test: TestSuite::Tester { + explicit GenericGL_Test(); + + void glslMatch(); + void glslMatchOutput(); + + void tbnContiguous(); + void tbnBothNormalAndQuaternion(); + void textureTransformContiguous(); +}; + +GenericGL_Test::GenericGL_Test() { + addTests({&GenericGL_Test::glslMatch, + &GenericGL_Test::glslMatchOutput, + + &GenericGL_Test::tbnContiguous, + &GenericGL_Test::tbnBothNormalAndQuaternion, + &GenericGL_Test::textureTransformContiguous}); +} + +void GenericGL_Test::glslMatch() { + CORRADE_COMPARE(POSITION_ATTRIBUTE_LOCATION, GenericGL2D::Position::Location); + CORRADE_COMPARE(POSITION_ATTRIBUTE_LOCATION, GenericGL3D::Position::Location); + + CORRADE_COMPARE(TEXTURECOORDINATES_ATTRIBUTE_LOCATION, GenericGL2D::TextureCoordinates::Location); + CORRADE_COMPARE(TEXTURECOORDINATES_ATTRIBUTE_LOCATION, GenericGL3D::TextureCoordinates::Location); + + CORRADE_COMPARE(COLOR_ATTRIBUTE_LOCATION, GenericGL2D::Color3::Location); + CORRADE_COMPARE(COLOR_ATTRIBUTE_LOCATION, GenericGL3D::Color3::Location); + CORRADE_COMPARE(COLOR_ATTRIBUTE_LOCATION, GenericGL2D::Color4::Location); + CORRADE_COMPARE(COLOR_ATTRIBUTE_LOCATION, GenericGL3D::Color4::Location); + + #ifndef MAGNUM_TARGET_GLES2 + CORRADE_COMPARE(OBJECT_ID_ATTRIBUTE_LOCATION, GenericGL2D::ObjectId::Location); + CORRADE_COMPARE(OBJECT_ID_ATTRIBUTE_LOCATION, GenericGL3D::ObjectId::Location); + #endif + + CORRADE_COMPARE(TANGENT_ATTRIBUTE_LOCATION, GenericGL3D::Tangent::Location); + CORRADE_COMPARE(TANGENT_ATTRIBUTE_LOCATION, GenericGL3D::Tangent4::Location); + CORRADE_COMPARE(BITANGENT_ATTRIBUTE_LOCATION, GenericGL3D::Bitangent::Location); + CORRADE_COMPARE(NORMAL_ATTRIBUTE_LOCATION, GenericGL3D::Normal::Location); + + CORRADE_COMPARE(TRANSFORMATION_MATRIX_ATTRIBUTE_LOCATION, GenericGL2D::TransformationMatrix::Location); + CORRADE_COMPARE(TRANSFORMATION_MATRIX_ATTRIBUTE_LOCATION, GenericGL3D::TransformationMatrix::Location); + + CORRADE_COMPARE(NORMAL_MATRIX_ATTRIBUTE_LOCATION, GenericGL3D::NormalMatrix::Location); + + CORRADE_COMPARE(TEXTURE_OFFSET_ATTRIBUTE_LOCATION, GenericGL2D::TextureOffset::Location); + CORRADE_COMPARE(TEXTURE_OFFSET_ATTRIBUTE_LOCATION, GenericGL3D::TextureOffset::Location); +} + +void GenericGL_Test::glslMatchOutput() { + CORRADE_COMPARE(COLOR_OUTPUT_ATTRIBUTE_LOCATION, GenericGL2D::ColorOutput); + CORRADE_COMPARE(COLOR_OUTPUT_ATTRIBUTE_LOCATION, GenericGL3D::ColorOutput); + + #ifndef MAGNUM_TARGET_GLES2 + CORRADE_COMPARE(OBJECT_ID_OUTPUT_ATTRIBUTE_LOCATION, GenericGL2D::ObjectIdOutput); + CORRADE_COMPARE(OBJECT_ID_OUTPUT_ATTRIBUTE_LOCATION, GenericGL3D::ObjectIdOutput); + #endif +} + +void GenericGL_Test::tbnContiguous() { + CORRADE_COMPARE(GenericGL3D::Tangent::Location + 1, GenericGL3D::Bitangent::Location); + CORRADE_COMPARE(GenericGL3D::Bitangent::Location + 1, GenericGL3D::Normal::Location); +} + +void GenericGL_Test::tbnBothNormalAndQuaternion() { + CORRADE_SKIP("Quaternion TBN not implemented yet."); + + //CORRADE_VERIFY(GenericGL3D::TbnQuaternion::Location != GenericGL3D::Normal::Location); +} + +void GenericGL_Test::textureTransformContiguous() { + /* These depend on DualQuaternion-based (instanced) transformation */ + CORRADE_SKIP("TextureRotationScale and TextureMatrix attributes not implemented yet."); + + //CORRADE_COMPARE(GenericGL3D::TextureRotationScale::Location, GenericGL3D::TextureMatrix::Location); + //CORRADE_COMPARE(GenericGL3D::TextureOffset::Location, GenericGL3D::TextureMatrix::Location + 2); +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Shaders::Test::GenericGL_Test) diff --git a/src/Magnum/Shaders/Test/GenericTest.cpp b/src/Magnum/Shaders/Test/GenericTest.cpp index 08e747193..e69de29bb 100644 --- a/src/Magnum/Shaders/Test/GenericTest.cpp +++ b/src/Magnum/Shaders/Test/GenericTest.cpp @@ -1,116 +0,0 @@ -/* - This file is part of Magnum. - - Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, - 2020, 2021 Vladimír Vondruš - - 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 - -#include "Magnum/Shaders/Generic.h" -/* Yes, really */ -#include "Magnum/Shaders/generic.glsl" - -namespace Magnum { namespace Shaders { namespace Test { namespace { - -struct GenericTest: TestSuite::Tester { - explicit GenericTest(); - - void glslMatch(); - void glslMatchOutput(); - - void tbnContiguous(); - void tbnBothNormalAndQuaternion(); - void textureTransformContiguous(); -}; - -GenericTest::GenericTest() { - addTests({&GenericTest::glslMatch, - &GenericTest::glslMatchOutput, - - &GenericTest::tbnContiguous, - &GenericTest::tbnBothNormalAndQuaternion, - &GenericTest::textureTransformContiguous}); -} - -void GenericTest::glslMatch() { - CORRADE_COMPARE(POSITION_ATTRIBUTE_LOCATION, Generic2D::Position::Location); - CORRADE_COMPARE(POSITION_ATTRIBUTE_LOCATION, Generic3D::Position::Location); - - CORRADE_COMPARE(TEXTURECOORDINATES_ATTRIBUTE_LOCATION, Generic2D::TextureCoordinates::Location); - CORRADE_COMPARE(TEXTURECOORDINATES_ATTRIBUTE_LOCATION, Generic3D::TextureCoordinates::Location); - - CORRADE_COMPARE(COLOR_ATTRIBUTE_LOCATION, Generic2D::Color3::Location); - CORRADE_COMPARE(COLOR_ATTRIBUTE_LOCATION, Generic3D::Color3::Location); - CORRADE_COMPARE(COLOR_ATTRIBUTE_LOCATION, Generic2D::Color4::Location); - CORRADE_COMPARE(COLOR_ATTRIBUTE_LOCATION, Generic3D::Color4::Location); - - #ifndef MAGNUM_TARGET_GLES2 - CORRADE_COMPARE(OBJECT_ID_ATTRIBUTE_LOCATION, Generic2D::ObjectId::Location); - CORRADE_COMPARE(OBJECT_ID_ATTRIBUTE_LOCATION, Generic3D::ObjectId::Location); - #endif - - CORRADE_COMPARE(TANGENT_ATTRIBUTE_LOCATION, Generic3D::Tangent::Location); - CORRADE_COMPARE(TANGENT_ATTRIBUTE_LOCATION, Generic3D::Tangent4::Location); - CORRADE_COMPARE(BITANGENT_ATTRIBUTE_LOCATION, Generic3D::Bitangent::Location); - CORRADE_COMPARE(NORMAL_ATTRIBUTE_LOCATION, Generic3D::Normal::Location); - - CORRADE_COMPARE(TRANSFORMATION_MATRIX_ATTRIBUTE_LOCATION, Generic2D::TransformationMatrix::Location); - CORRADE_COMPARE(TRANSFORMATION_MATRIX_ATTRIBUTE_LOCATION, Generic3D::TransformationMatrix::Location); - - CORRADE_COMPARE(NORMAL_MATRIX_ATTRIBUTE_LOCATION, Generic3D::NormalMatrix::Location); - - CORRADE_COMPARE(TEXTURE_OFFSET_ATTRIBUTE_LOCATION, Generic2D::TextureOffset::Location); - CORRADE_COMPARE(TEXTURE_OFFSET_ATTRIBUTE_LOCATION, Generic3D::TextureOffset::Location); -} - -void GenericTest::glslMatchOutput() { - CORRADE_COMPARE(COLOR_OUTPUT_ATTRIBUTE_LOCATION, Generic2D::ColorOutput); - CORRADE_COMPARE(COLOR_OUTPUT_ATTRIBUTE_LOCATION, Generic3D::ColorOutput); - - #ifndef MAGNUM_TARGET_GLES2 - CORRADE_COMPARE(OBJECT_ID_OUTPUT_ATTRIBUTE_LOCATION, Generic2D::ObjectIdOutput); - CORRADE_COMPARE(OBJECT_ID_OUTPUT_ATTRIBUTE_LOCATION, Generic3D::ObjectIdOutput); - #endif -} - -void GenericTest::tbnContiguous() { - CORRADE_COMPARE(Generic3D::Tangent::Location + 1, Generic3D::Bitangent::Location); - CORRADE_COMPARE(Generic3D::Bitangent::Location + 1, Generic3D::Normal::Location); -} - -void GenericTest::tbnBothNormalAndQuaternion() { - CORRADE_SKIP("Quaternion TBN not implemented yet."); - - //CORRADE_VERIFY(Generic3D::TbnQuaternion::Location != Generic3D::Normal::Location); -} - -void GenericTest::textureTransformContiguous() { - /* These depend on DualQuaternion-based (instanced) transformation */ - CORRADE_SKIP("TextureRotationScale and TextureMatrix attributes not implemented yet."); - - //CORRADE_COMPARE(Generic3D::TextureRotationScale::Location, Generic3D::TextureMatrix::Location); - //CORRADE_COMPARE(Generic3D::TextureOffset::Location, Generic3D::TextureMatrix::Location + 2); -} - -}}}} - -CORRADE_TEST_MAIN(Magnum::Shaders::Test::GenericTest) diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp index 6cab62742..183d504f4 100644 --- a/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp +++ b/src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp @@ -57,7 +57,7 @@ #include "Magnum/Primitives/Icosphere.h" #include "Magnum/Primitives/Plane.h" #include "Magnum/Primitives/UVSphere.h" -#include "Magnum/Shaders/MeshVisualizer.h" +#include "Magnum/Shaders/MeshVisualizerGL.h" #include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/MeshData.h" @@ -153,60 +153,60 @@ using namespace Math::Literals; constexpr struct { const char* name; - MeshVisualizer2D::Flags flags; + MeshVisualizerGL2D::Flags flags; } ConstructData2D[] { - {"wireframe w/o GS", MeshVisualizer2D::Flag::Wireframe|MeshVisualizer2D::Flag::NoGeometryShader}, + {"wireframe w/o GS", MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader}, #ifndef MAGNUM_TARGET_GLES2 - {"object ID", MeshVisualizer2D::Flag::InstancedObjectId}, - {"vertex ID", MeshVisualizer2D::Flag::VertexId}, + {"object ID", MeshVisualizerGL2D::Flag::InstancedObjectId}, + {"vertex ID", MeshVisualizerGL2D::Flag::VertexId}, #ifndef MAGNUM_TARGET_WEBGL - {"primitive ID", MeshVisualizer2D::Flag::PrimitiveId}, + {"primitive ID", MeshVisualizerGL2D::Flag::PrimitiveId}, #endif - {"primitive ID from vertex ID", MeshVisualizer2D::Flag::PrimitiveIdFromVertexId} + {"primitive ID from vertex ID", MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId} #endif }; constexpr struct { const char* name; - MeshVisualizer3D::Flags flags; + MeshVisualizerGL3D::Flags flags; } ConstructData3D[] { - {"wireframe w/o GS", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::NoGeometryShader}, + {"wireframe w/o GS", MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader}, #ifndef MAGNUM_TARGET_GLES2 - {"object ID", MeshVisualizer3D::Flag::InstancedObjectId}, - {"vertex ID", MeshVisualizer3D::Flag::VertexId}, + {"object ID", MeshVisualizerGL3D::Flag::InstancedObjectId}, + {"vertex ID", MeshVisualizerGL3D::Flag::VertexId}, #ifndef MAGNUM_TARGET_WEBGL - {"primitive ID", MeshVisualizer3D::Flag::PrimitiveId}, + {"primitive ID", MeshVisualizerGL3D::Flag::PrimitiveId}, #endif - {"primitive ID from vertex ID", MeshVisualizer3D::Flag::PrimitiveIdFromVertexId} + {"primitive ID from vertex ID", MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId} #endif }; #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) constexpr struct { const char* name; - MeshVisualizer3D::Flags flags; + MeshVisualizerGL3D::Flags flags; } ConstructGeometryShaderData3D[] { - {"wireframe", MeshVisualizer3D::Flag::Wireframe}, - {"tangent direction", MeshVisualizer3D::Flag::TangentDirection}, - {"bitangent direction from tangent", MeshVisualizer3D::Flag::BitangentFromTangentDirection}, - {"bitangent direction", MeshVisualizer3D::Flag::BitangentDirection}, - {"normal direction", MeshVisualizer3D::Flag::NormalDirection}, - {"tbn direction", MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::BitangentDirection|MeshVisualizer3D::Flag::NormalDirection}, - {"tbn direction with bitangent from tangent", MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::BitangentFromTangentDirection|MeshVisualizer3D::Flag::NormalDirection}, - {"wireframe + vertex id", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::VertexId}, - {"wireframe + t/n direction", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::NormalDirection}, - {"wireframe + object id + t/n direction", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::InstancedObjectId|MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::NormalDirection}, - {"wireframe + vertex id + t/b direction", MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::VertexId|MeshVisualizer3D::Flag::TangentDirection|MeshVisualizer3D::Flag::BitangentDirection} + {"wireframe", MeshVisualizerGL3D::Flag::Wireframe}, + {"tangent direction", MeshVisualizerGL3D::Flag::TangentDirection}, + {"bitangent direction from tangent", MeshVisualizerGL3D::Flag::BitangentFromTangentDirection}, + {"bitangent direction", MeshVisualizerGL3D::Flag::BitangentDirection}, + {"normal direction", MeshVisualizerGL3D::Flag::NormalDirection}, + {"tbn direction", MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection|MeshVisualizerGL3D::Flag::NormalDirection}, + {"tbn direction with bitangent from tangent", MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::NormalDirection}, + {"wireframe + vertex id", MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::VertexId}, + {"wireframe + t/n direction", MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::NormalDirection}, + {"wireframe + object id + t/n direction", MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::InstancedObjectId|MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::NormalDirection}, + {"wireframe + vertex id + t/b direction", MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::VertexId|MeshVisualizerGL3D::Flag::TangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection} }; #endif constexpr struct { const char* name; - MeshVisualizer2D::Flags flags; + MeshVisualizerGL2D::Flags flags; const char* message; } ConstructInvalidData2D[] { {"no feature enabled", - MeshVisualizer2D::Flag::NoGeometryShader, /* not a feature flag */ + MeshVisualizerGL2D::Flag::NoGeometryShader, /* not a feature flag */ #ifndef MAGNUM_TARGET_GLES2 "2D: at least one visualization feature has to be enabled" #else @@ -215,21 +215,21 @@ constexpr struct { }, #ifndef MAGNUM_TARGET_GLES2 {"both object and primitive id", - MeshVisualizer2D::Flag::InstancedObjectId|MeshVisualizer2D::Flag::PrimitiveIdFromVertexId, + MeshVisualizerGL2D::Flag::InstancedObjectId|MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId, ": Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive"}, {"both object and vertex id", - MeshVisualizer2D::Flag::InstancedObjectId|MeshVisualizer2D::Flag::VertexId, + MeshVisualizerGL2D::Flag::InstancedObjectId|MeshVisualizerGL2D::Flag::VertexId, ": Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive"} #endif }; constexpr struct { const char* name; - MeshVisualizer3D::Flags flags; + MeshVisualizerGL3D::Flags flags; const char* message; } ConstructInvalidData3D[] { {"no feature enabled", - MeshVisualizer3D::Flag::NoGeometryShader, /* not a feature flag */ + MeshVisualizerGL3D::Flag::NoGeometryShader, /* not a feature flag */ #ifndef MAGNUM_TARGET_GLES2 "3D: at least one visualization feature has to be enabled" #else @@ -238,10 +238,10 @@ constexpr struct { }, #ifndef MAGNUM_TARGET_GLES2 {"both object and primitive id", - MeshVisualizer3D::Flag::InstancedObjectId|MeshVisualizer3D::Flag::PrimitiveIdFromVertexId, + MeshVisualizerGL3D::Flag::InstancedObjectId|MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId, ": Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive"}, {"both vertex and primitive id", - MeshVisualizer3D::Flag::VertexId|MeshVisualizer3D::Flag::PrimitiveIdFromVertexId, + MeshVisualizerGL3D::Flag::VertexId|MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId, ": Flag::InstancedObjectId, Flag::VertexId and Flag::PrimitiveId are mutually exclusive"} #endif }; @@ -261,83 +261,83 @@ constexpr struct { constexpr struct { const char* name; - MeshVisualizer2D::Flags flags; + MeshVisualizerGL2D::Flags flags; Float width, smoothness; const char* file; const char* fileXfail; } WireframeData2D[] { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - {"", MeshVisualizer2D::Flags{}, + {"", MeshVisualizerGL2D::Flags{}, 1.0f, 2.0f, "wireframe2D.tga", nullptr}, - {"wide/sharp", MeshVisualizer2D::Flags{}, + {"wide/sharp", MeshVisualizerGL2D::Flags{}, 3.0f, 1.0f, "wireframe-wide2D.tga", nullptr}, #endif - {"no geometry shader", MeshVisualizer2D::Flag::NoGeometryShader, + {"no geometry shader", MeshVisualizerGL2D::Flag::NoGeometryShader, 1.0f, 2.0f, "wireframe2D.tga", "wireframe-nogeo2D.tga"}, - {"no geometry shader, wide/sharp", MeshVisualizer2D::Flag::NoGeometryShader, + {"no geometry shader, wide/sharp", MeshVisualizerGL2D::Flag::NoGeometryShader, 3.0f, 1.0f, "wireframe-wide2D.tga", "wireframe-nogeo2D.tga"} }; constexpr struct { const char* name; - MeshVisualizer3D::Flags flags; + MeshVisualizerGL3D::Flags flags; Float width, smoothness; const char* file; const char* fileXfail; } WireframeData3D[] { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - {"", MeshVisualizer3D::Flags{}, + {"", MeshVisualizerGL3D::Flags{}, 1.0f, 2.0f, "wireframe3D.tga", nullptr}, - {"wide/sharp", MeshVisualizer3D::Flags{}, + {"wide/sharp", MeshVisualizerGL3D::Flags{}, 3.0f, 1.0f, "wireframe-wide3D.tga", nullptr}, #endif {"no geometry shader", - MeshVisualizer3D::Flag::NoGeometryShader, + MeshVisualizerGL3D::Flag::NoGeometryShader, 1.0f, 2.0f, "wireframe3D.tga", "wireframe-nogeo3D.tga"}, {"no geometry shader, wide/sharp", - MeshVisualizer3D::Flag::NoGeometryShader, + MeshVisualizerGL3D::Flag::NoGeometryShader, 3.0f, 1.0f, "wireframe-wide3D.tga", "wireframe-nogeo3D.tga"} }; #ifndef MAGNUM_TARGET_GLES2 constexpr struct { const char* name; - MeshVisualizer2D::Flags flags2D; - MeshVisualizer3D::Flags flags3D; + MeshVisualizerGL2D::Flags flags2D; + MeshVisualizerGL3D::Flags flags3D; const char* file2D; const char* file3D; } ObjectVertexPrimitiveIdData[] { {"object ID", - MeshVisualizer2D::Flag::InstancedObjectId, - MeshVisualizer3D::Flag::InstancedObjectId, + MeshVisualizerGL2D::Flag::InstancedObjectId, + MeshVisualizerGL3D::Flag::InstancedObjectId, "objectid2D.tga", "objectid3D.tga"}, {"vertex ID", - MeshVisualizer2D::Flag::VertexId, - MeshVisualizer3D::Flag::VertexId, + MeshVisualizerGL2D::Flag::VertexId, + MeshVisualizerGL3D::Flag::VertexId, "vertexid2D.tga", "vertexid3D.tga"}, #ifndef MAGNUM_TARGET_WEBGL {"primitive ID", - MeshVisualizer2D::Flag::PrimitiveId, - MeshVisualizer3D::Flag::PrimitiveId, + MeshVisualizerGL2D::Flag::PrimitiveId, + MeshVisualizerGL3D::Flag::PrimitiveId, "primitiveid2D.tga", "primitiveid3D.tga"}, #endif {"primitive ID from vertex ID", - MeshVisualizer2D::Flag::PrimitiveIdFromVertexId, - MeshVisualizer3D::Flag::PrimitiveIdFromVertexId, + MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId, + MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId, "primitiveid2D.tga", "primitiveid3D.tga"}, {"wireframe + object ID", - MeshVisualizer2D::Flag::InstancedObjectId|MeshVisualizer2D::Flag::Wireframe, - MeshVisualizer3D::Flag::InstancedObjectId|MeshVisualizer3D::Flag::Wireframe, + MeshVisualizerGL2D::Flag::InstancedObjectId|MeshVisualizerGL2D::Flag::Wireframe, + MeshVisualizerGL3D::Flag::InstancedObjectId|MeshVisualizerGL3D::Flag::Wireframe, "wireframe-objectid2D.tga", "wireframe-objectid3D.tga"}, {"wireframe + object ID, no geometry shader", - MeshVisualizer2D::Flag::InstancedObjectId|MeshVisualizer2D::Flag::Wireframe| - MeshVisualizer2D::Flag::NoGeometryShader, - MeshVisualizer3D::Flag::InstancedObjectId|MeshVisualizer3D::Flag::Wireframe| - MeshVisualizer3D::Flag::NoGeometryShader, + MeshVisualizerGL2D::Flag::InstancedObjectId|MeshVisualizerGL2D::Flag::Wireframe| + MeshVisualizerGL2D::Flag::NoGeometryShader, + MeshVisualizerGL3D::Flag::InstancedObjectId|MeshVisualizerGL3D::Flag::Wireframe| + MeshVisualizerGL3D::Flag::NoGeometryShader, "wireframe-nogeo-objectid2D.tga", "wireframe-nogeo-objectid3D.tga"}, {"wireframe + vertex ID", - MeshVisualizer2D::Flag::VertexId|MeshVisualizer2D::Flag::Wireframe, - MeshVisualizer3D::Flag::VertexId|MeshVisualizer3D::Flag::Wireframe, + MeshVisualizerGL2D::Flag::VertexId|MeshVisualizerGL2D::Flag::Wireframe, + MeshVisualizerGL3D::Flag::VertexId|MeshVisualizerGL3D::Flag::Wireframe, "wireframe-vertexid2D.tga", "wireframe-vertexid3D.tga"} }; #endif @@ -345,8 +345,8 @@ constexpr struct { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) constexpr struct { const char* name; - MeshVisualizer3D::Flags flags; - MeshVisualizer3D::Flags secondPassFlags; + MeshVisualizerGL3D::Flags flags; + MeshVisualizerGL3D::Flags secondPassFlags; bool skipBitagnentEvenIfEnabledInFlags; Float smoothness; Float lineWidth; @@ -355,50 +355,50 @@ constexpr struct { const char* file; } TangentBitangentNormalData[] { {"", - MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::BitangentDirection| - MeshVisualizer3D::Flag::NormalDirection, {}, + MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::BitangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection, {}, false, 2.0f, 1.0f, 0.6f, 1.0f, "tbn.tga"}, {"bitangents from tangents", - MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::BitangentFromTangentDirection| - MeshVisualizer3D::Flag::NormalDirection, {}, + MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::BitangentFromTangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection, {}, false, 2.0f, 1.0f, 0.6f, 1.0f, "tbn.tga"}, {"scaled data", - MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::BitangentDirection| - MeshVisualizer3D::Flag::NormalDirection, {}, + MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::BitangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection, {}, false, 2.0f, 1.0f, 0.6f, 5.0f, "tbn.tga"}, {"wide blurry lines", - MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::BitangentDirection| - MeshVisualizer3D::Flag::NormalDirection, {}, + MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::BitangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection, {}, false, 5.0f, 5.0f, 0.8f, 1.0f, "tbn-wide.tga"}, {"only bitangent from tangent", - MeshVisualizer3D::Flag::BitangentFromTangentDirection, {}, + MeshVisualizerGL3D::Flag::BitangentFromTangentDirection, {}, false, 2.0f, 1.0f, 0.6f, 1.0f, "bitangents-from-tangents.tga"}, {"wireframe + primitive ID + tangents + normals, single pass", - MeshVisualizer3D::Flag::Wireframe| - MeshVisualizer3D::Flag::PrimitiveId| - MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::NormalDirection, {}, + MeshVisualizerGL3D::Flag::Wireframe| + MeshVisualizerGL3D::Flag::PrimitiveId| + MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection, {}, false, 2.0f, 1.0f, 0.6f, 1.0f, "wireframe-primitiveid-tn.tga"}, {"wireframe + primitive ID, rendering all, but only tangents + normals present", - MeshVisualizer3D::Flag::Wireframe| - MeshVisualizer3D::Flag::PrimitiveId| - MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::BitangentDirection| - MeshVisualizer3D::Flag::NormalDirection, {}, + MeshVisualizerGL3D::Flag::Wireframe| + MeshVisualizerGL3D::Flag::PrimitiveId| + MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::BitangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection, {}, true, 2.0f, 1.0f, 0.6f, 1.0f, "wireframe-primitiveid-tn.tga"}, {"wireframe + tangents + normals, two passes", - MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::NormalDirection, - MeshVisualizer3D::Flag::Wireframe, + MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection, + MeshVisualizerGL3D::Flag::Wireframe, false, 2.0f, 1.0f, 0.6f, 1.0f, "wireframe-tn-smooth.tga"}, {"primitive ID + tangents + normals", - MeshVisualizer3D::Flag::PrimitiveId| - MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::NormalDirection, {}, + MeshVisualizerGL3D::Flag::PrimitiveId| + MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection, {}, false, 2.0f, 1.0f, 0.6f, 1.0f, "primitiveid-tn.tga"} }; #endif @@ -543,12 +543,12 @@ void MeshVisualizerGLTest::construct2D() { setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES - if((data.flags & MeshVisualizer2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) + if((data.flags & MeshVisualizerGL2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags >= MeshVisualizer2D::Flag::PrimitiveIdFromVertexId && + if(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId && #ifndef MAGNUM_TARGET_GLES !GL::Context::current().isVersionSupported(GL::Version::GL300) #else @@ -558,7 +558,7 @@ void MeshVisualizerGLTest::construct2D() { #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags & MeshVisualizer2D::Flag::PrimitiveId && !(data.flags >= MeshVisualizer2D::Flag::PrimitiveIdFromVertexId) && + if(data.flags & MeshVisualizerGL2D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) && #ifndef MAGNUM_TARGET_GLES !GL::Context::current().isVersionSupported(GL::Version::GL320) #else @@ -567,7 +567,7 @@ void MeshVisualizerGLTest::construct2D() { ) CORRADE_SKIP("gl_PrimitiveID not supported."); #endif - MeshVisualizer2D shader{data.flags}; + MeshVisualizerGL2D shader{data.flags}; CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_VERIFY(shader.id()); { @@ -585,12 +585,12 @@ void MeshVisualizerGLTest::construct3D() { setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES - if((data.flags & MeshVisualizer3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) + if((data.flags & MeshVisualizerGL3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags >= MeshVisualizer3D::Flag::PrimitiveIdFromVertexId && + if(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId && #ifndef MAGNUM_TARGET_GLES !GL::Context::current().isVersionSupported(GL::Version::GL300) #else @@ -600,7 +600,7 @@ void MeshVisualizerGLTest::construct3D() { #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags & MeshVisualizer3D::Flag::PrimitiveId && !(data.flags >= MeshVisualizer3D::Flag::PrimitiveIdFromVertexId) && + if(data.flags & MeshVisualizerGL3D::Flag::PrimitiveId && !(data.flags >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId) && #ifndef MAGNUM_TARGET_GLES !GL::Context::current().isVersionSupported(GL::Version::GL320) #else @@ -609,7 +609,7 @@ void MeshVisualizerGLTest::construct3D() { ) CORRADE_SKIP("gl_PrimitiveID not supported."); #endif - MeshVisualizer3D shader{data.flags}; + MeshVisualizerGL3D shader{data.flags}; CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_VERIFY(shader.id()); { @@ -637,8 +637,8 @@ void MeshVisualizerGLTest::constructWireframeGeometryShader2D() { Debug() << "Using" << GL::Extensions::NV::shader_noperspective_interpolation::string(); #endif - MeshVisualizer2D shader{MeshVisualizer2D::Flag::Wireframe}; - CORRADE_COMPARE(shader.flags(), MeshVisualizer2D::Flag::Wireframe); + MeshVisualizerGL2D shader{MeshVisualizerGL2D::Flag::Wireframe}; + CORRADE_COMPARE(shader.flags(), MeshVisualizerGL2D::Flag::Wireframe); { #ifdef CORRADE_TARGET_APPLE CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); @@ -665,7 +665,7 @@ void MeshVisualizerGLTest::constructGeometryShader3D() { Debug() << "Using" << GL::Extensions::NV::shader_noperspective_interpolation::string(); #endif - MeshVisualizer3D shader{data.flags}; + MeshVisualizerGL3D shader{data.flags}; CORRADE_COMPARE(shader.flags(), data.flags); { #ifdef CORRADE_TARGET_APPLE @@ -687,8 +687,8 @@ void MeshVisualizerGLTest::construct2DInvalid() { std::ostringstream out; Error redirectError{&out}; - MeshVisualizer2D{data.flags}; - CORRADE_COMPARE(out.str(), Utility::formatString("Shaders::MeshVisualizer{}\n", data.message)); + MeshVisualizerGL2D{data.flags}; + CORRADE_COMPARE(out.str(), Utility::formatString("Shaders::MeshVisualizerGL{}\n", data.message)); } void MeshVisualizerGLTest::construct3DInvalid() { @@ -701,8 +701,8 @@ void MeshVisualizerGLTest::construct3DInvalid() { std::ostringstream out; Error redirectError{&out}; - MeshVisualizer3D{data.flags}; - CORRADE_COMPARE(out.str(), Utility::formatString("Shaders::MeshVisualizer{}\n", data.message)); + MeshVisualizerGL3D{data.flags}; + CORRADE_COMPARE(out.str(), Utility::formatString("Shaders::MeshVisualizerGL{}\n", data.message)); } #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -721,9 +721,9 @@ void MeshVisualizerGLTest::construct3DGeometryShaderDisabledButNeeded() { std::ostringstream out; Error redirectError{&out}; - MeshVisualizer3D{MeshVisualizer3D::Flag::NoGeometryShader|MeshVisualizer3D::Flag::NormalDirection}; + MeshVisualizerGL3D{MeshVisualizerGL3D::Flag::NoGeometryShader|MeshVisualizerGL3D::Flag::NormalDirection}; CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer3D: geometry shader has to be enabled when rendering TBN direction\n"); + "Shaders::MeshVisualizerGL3D: geometry shader has to be enabled when rendering TBN direction\n"); } void MeshVisualizerGLTest::construct3DConflictingBitangentInput() { @@ -741,47 +741,47 @@ void MeshVisualizerGLTest::construct3DConflictingBitangentInput() { std::ostringstream out; Error redirectError{&out}; - MeshVisualizer3D{MeshVisualizer3D::Flag::BitangentFromTangentDirection|MeshVisualizer3D::Flag::BitangentDirection}; + MeshVisualizerGL3D{MeshVisualizerGL3D::Flag::BitangentFromTangentDirection|MeshVisualizerGL3D::Flag::BitangentDirection}; CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive\n"); + "Shaders::MeshVisualizerGL3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive\n"); } #endif void MeshVisualizerGLTest::constructMove2D() { - MeshVisualizer2D a{MeshVisualizer2D::Flag::Wireframe|MeshVisualizer2D::Flag::NoGeometryShader}; + MeshVisualizerGL2D a{MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader}; const GLuint id = a.id(); CORRADE_VERIFY(id); MAGNUM_VERIFY_NO_GL_ERROR(); - MeshVisualizer2D b{std::move(a)}; + MeshVisualizerGL2D b{std::move(a)}; CORRADE_COMPARE(b.id(), id); - CORRADE_COMPARE(b.flags(), MeshVisualizer2D::Flag::Wireframe|MeshVisualizer2D::Flag::NoGeometryShader); + CORRADE_COMPARE(b.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); CORRADE_VERIFY(!a.id()); - MeshVisualizer2D c{NoCreate}; + MeshVisualizerGL2D c{NoCreate}; c = std::move(b); CORRADE_COMPARE(c.id(), id); - CORRADE_COMPARE(c.flags(), MeshVisualizer2D::Flag::Wireframe|MeshVisualizer2D::Flag::NoGeometryShader); + CORRADE_COMPARE(c.flags(), MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader); CORRADE_VERIFY(!b.id()); } void MeshVisualizerGLTest::constructMove3D() { - MeshVisualizer3D a{MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::NoGeometryShader}; + MeshVisualizerGL3D a{MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader}; const GLuint id = a.id(); CORRADE_VERIFY(id); MAGNUM_VERIFY_NO_GL_ERROR(); - MeshVisualizer3D b{std::move(a)}; + MeshVisualizerGL3D b{std::move(a)}; CORRADE_COMPARE(b.id(), id); - CORRADE_COMPARE(b.flags(), MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::NoGeometryShader); + CORRADE_COMPARE(b.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); CORRADE_VERIFY(!a.id()); - MeshVisualizer3D c{NoCreate}; + MeshVisualizerGL3D c{NoCreate}; c = std::move(b); CORRADE_COMPARE(c.id(), id); - CORRADE_COMPARE(c.flags(), MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::NoGeometryShader); + CORRADE_COMPARE(c.flags(), MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader); CORRADE_VERIFY(!b.id()); } @@ -795,16 +795,16 @@ void MeshVisualizerGLTest::setWireframeNotEnabled2D() { /* The constructor asserts for at least some feature being enabled (which is just wireframe in case of 2D), so fake it with a NoCreate */ - MeshVisualizer2D shader{NoCreate}; + MeshVisualizerGL2D shader{NoCreate}; shader .setColor({}); #ifndef MAGNUM_TARGET_GLES2 CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled\n"); + "Shaders::MeshVisualizerGL::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled\n"); #else CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe enabled\n"); + "Shaders::MeshVisualizerGL::setColor(): the shader was not created with wireframe enabled\n"); #endif out.str({}); @@ -814,9 +814,9 @@ void MeshVisualizerGLTest::setWireframeNotEnabled2D() { .setSmoothness({}); CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setWireframeColor(): the shader was not created with wireframe enabled\n" - "Shaders::MeshVisualizer::setWireframeWidth(): the shader was not created with wireframe enabled\n" - "Shaders::MeshVisualizer2D::setSmoothness(): the shader was not created with wireframe enabled\n"); + "Shaders::MeshVisualizerGL::setWireframeColor(): the shader was not created with wireframe enabled\n" + "Shaders::MeshVisualizerGL::setWireframeWidth(): the shader was not created with wireframe enabled\n" + "Shaders::MeshVisualizerGL2D::setSmoothness(): the shader was not created with wireframe enabled\n"); } void MeshVisualizerGLTest::setWireframeNotEnabled3D() { @@ -830,16 +830,16 @@ void MeshVisualizerGLTest::setWireframeNotEnabled3D() { /* The constructor asserts for at least some feature being enabled (which is just wireframe in case we're not on desktop or ES3.2), so fake it with a NoCreate */ - MeshVisualizer3D shader{NoCreate}; + MeshVisualizerGL3D shader{NoCreate}; shader .setColor({}); #ifndef MAGNUM_TARGET_GLES2 CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled\n"); + "Shaders::MeshVisualizerGL::setColor(): the shader was not created with wireframe or object/vertex/primitive ID enabled\n"); #else CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColor(): the shader was not created with wireframe enabled\n"); + "Shaders::MeshVisualizerGL::setColor(): the shader was not created with wireframe enabled\n"); #endif out.str({}); @@ -849,9 +849,9 @@ void MeshVisualizerGLTest::setWireframeNotEnabled3D() { .setSmoothness({}); CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setWireframeColor(): the shader was not created with wireframe enabled\n" - "Shaders::MeshVisualizer::setWireframeWidth(): the shader was not created with wireframe enabled\n" - "Shaders::MeshVisualizer3D::setSmoothness(): the shader was not created with wireframe or TBN direction enabled\n"); + "Shaders::MeshVisualizerGL::setWireframeColor(): the shader was not created with wireframe enabled\n" + "Shaders::MeshVisualizerGL::setWireframeWidth(): the shader was not created with wireframe enabled\n" + "Shaders::MeshVisualizerGL3D::setSmoothness(): the shader was not created with wireframe or TBN direction enabled\n"); } #ifndef MAGNUM_TARGET_GLES2 @@ -864,13 +864,13 @@ void MeshVisualizerGLTest::setColorMapNotEnabled2D() { Error redirectError{&out}; GL::Texture2D texture; - MeshVisualizer2D shader{NoCreate}; + MeshVisualizerGL2D shader{NoCreate}; shader.setColorMapTransformation({}, {}) .bindColorMapTexture(texture); CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled\n" - "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled\n"); + "Shaders::MeshVisualizerGL::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled\n" + "Shaders::MeshVisualizerGL::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled\n"); } void MeshVisualizerGLTest::setColorMapNotEnabled3D() { @@ -882,13 +882,13 @@ void MeshVisualizerGLTest::setColorMapNotEnabled3D() { Error redirectError{&out}; GL::Texture2D texture; - MeshVisualizer3D shader{NoCreate}; + MeshVisualizerGL3D shader{NoCreate}; shader.setColorMapTransformation({}, {}) .bindColorMapTexture(texture); CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled\n" - "Shaders::MeshVisualizer::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled\n"); + "Shaders::MeshVisualizerGL::setColorMapTransformation(): the shader was not created with object/vertex/primitive ID enabled\n" + "Shaders::MeshVisualizerGL::bindColorMapTexture(): the shader was not created with object/vertex/primitive ID enabled\n"); } #endif @@ -909,15 +909,15 @@ void MeshVisualizerGLTest::setTangentBitangentNormalNotEnabled3D() { std::ostringstream out; Error redirectError{&out}; - MeshVisualizer3D shader{MeshVisualizer3D::Flag::Wireframe}; + MeshVisualizerGL3D shader{MeshVisualizerGL3D::Flag::Wireframe}; shader.setNormalMatrix({}) .setLineWidth({}) .setLineLength({}); CORRADE_COMPARE(out.str(), - "Shaders::MeshVisualizer3D::setNormalMatrix(): the shader was not created with TBN direction enabled\n" - "Shaders::MeshVisualizer3D::setLineWidth(): the shader was not created with TBN direction enabled\n" - "Shaders::MeshVisualizer3D::setLineLength(): the shader was not created with TBN direction enabled\n"); + "Shaders::MeshVisualizerGL3D::setNormalMatrix(): the shader was not created with TBN direction enabled\n" + "Shaders::MeshVisualizerGL3D::setLineWidth(): the shader was not created with TBN direction enabled\n" + "Shaders::MeshVisualizerGL3D::setLineLength(): the shader was not created with TBN direction enabled\n"); } #endif @@ -974,7 +974,7 @@ void MeshVisualizerGLTest::renderDefaultsWireframe2D() { GL::Mesh circle = MeshTools::compile(Primitives::circle2DSolid(16)); - MeshVisualizer2D shader{MeshVisualizer2D::Flag::Wireframe}; + MeshVisualizerGL2D shader{MeshVisualizerGL2D::Flag::Wireframe}; shader.draw(circle); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -1023,7 +1023,7 @@ void MeshVisualizerGLTest::renderDefaultsWireframe3D() { GL::Mesh sphere = MeshTools::compile(Primitives::icosphereSolid(1)); - MeshVisualizer3D shader{MeshVisualizer3D::Flag::Wireframe}; + MeshVisualizerGL3D shader{MeshVisualizerGL3D::Flag::Wireframe}; shader.draw(sphere); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -1089,7 +1089,7 @@ void MeshVisualizerGLTest::renderDefaultsObjectId2D() { Containers::arrayView(ids)} })); - MeshVisualizer2D{MeshVisualizer2D::Flag::InstancedObjectId} + MeshVisualizerGL2D{MeshVisualizerGL2D::Flag::InstancedObjectId} .bindColorMapTexture(colorMapTexture) .draw(circle); @@ -1138,7 +1138,7 @@ void MeshVisualizerGLTest::renderDefaultsObjectId3D() { Containers::arrayView(ids)} })); - MeshVisualizer3D{MeshVisualizer3D::Flag::InstancedObjectId} + MeshVisualizerGL3D{MeshVisualizerGL3D::Flag::InstancedObjectId} .bindColorMapTexture(colorMapTexture) .draw(icosphere); @@ -1165,7 +1165,7 @@ void MeshVisualizerGLTest::renderDefaultsVertexId2D() { if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP("gl_VertexID not supported"); - MeshVisualizer2D{MeshVisualizer2D::Flag::VertexId} + MeshVisualizerGL2D{MeshVisualizerGL2D::Flag::VertexId} .bindColorMapTexture(_colorMapTexture) .draw(MeshTools::compile(Primitives::circle2DSolid(16))); @@ -1187,7 +1187,7 @@ void MeshVisualizerGLTest::renderDefaultsVertexId3D() { if(!GL::Context::current().isExtensionSupported()) CORRADE_SKIP("gl_VertexID not supported"); - MeshVisualizer2D{MeshVisualizer2D::Flag::VertexId} + MeshVisualizerGL2D{MeshVisualizerGL2D::Flag::VertexId} .bindColorMapTexture(_colorMapTexture) .draw(MeshTools::compile(Primitives::icosphereSolid(0))); @@ -1217,9 +1217,9 @@ void MeshVisualizerGLTest::renderDefaultsPrimitiveId2D() { ) CORRADE_SKIP("gl_VertexID not supported."); #endif - MeshVisualizer2D::Flags flags; + MeshVisualizerGL2D::Flags flags; #ifdef MAGNUM_TARGET_WEBGL - flags = MeshVisualizer2D::Flag::PrimitiveIdFromVertexId; + flags = MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId; #else #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isVersionSupported(GL::Version::GL320)) @@ -1228,16 +1228,16 @@ void MeshVisualizerGLTest::renderDefaultsPrimitiveId2D() { #endif { Debug{} << "Using primitive ID from vertex ID"; - flags = MeshVisualizer2D::Flag::PrimitiveIdFromVertexId; + flags = MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId; } - else flags = MeshVisualizer2D::Flag::PrimitiveId; + else flags = MeshVisualizerGL2D::Flag::PrimitiveId; #endif Trade::MeshData circleData = Primitives::circle2DSolid(16); - if(flags >= MeshVisualizer2D::Flag::PrimitiveIdFromVertexId) + if(flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) circleData = MeshTools::duplicate(MeshTools::generateIndices(circleData)); - MeshVisualizer2D{flags} + MeshVisualizerGL2D{flags} .bindColorMapTexture(_colorMapTexture) .draw(MeshTools::compile(circleData)); @@ -1269,9 +1269,9 @@ void MeshVisualizerGLTest::renderDefaultsPrimitiveId3D() { ) CORRADE_SKIP("gl_VertexID not supported."); #endif - MeshVisualizer2D::Flags flags; + MeshVisualizerGL2D::Flags flags; #ifdef MAGNUM_TARGET_WEBGL - flags = MeshVisualizer2D::Flag::PrimitiveIdFromVertexId; + flags = MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId; #else #ifndef MAGNUM_TARGET_GLES if(!GL::Context::current().isVersionSupported(GL::Version::GL320)) @@ -1280,16 +1280,16 @@ void MeshVisualizerGLTest::renderDefaultsPrimitiveId3D() { #endif { Debug{} << "Using primitive ID from vertex ID"; - flags = MeshVisualizer2D::Flag::PrimitiveIdFromVertexId; + flags = MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId; } - else flags = MeshVisualizer2D::Flag::PrimitiveId; + else flags = MeshVisualizerGL2D::Flag::PrimitiveId; #endif Trade::MeshData icosphereData = Primitives::icosphereSolid(0); - if(flags >= MeshVisualizer2D::Flag::PrimitiveIdFromVertexId) + if(flags >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) icosphereData = MeshTools::duplicate(icosphereData); - MeshVisualizer2D{flags} + MeshVisualizerGL2D{flags} .bindColorMapTexture(_colorMapTexture) .draw(MeshTools::compile(icosphereData)); @@ -1317,9 +1317,9 @@ void MeshVisualizerGLTest::renderDefaultsTangentBitangentNormal() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(4, 8, Primitives::UVSphereFlag::Tangents)); - MeshVisualizer3D{MeshVisualizer3D::Flag::TangentDirection| - MeshVisualizer3D::Flag::BitangentFromTangentDirection| - MeshVisualizer3D::Flag::NormalDirection} + MeshVisualizerGL3D{MeshVisualizerGL3D::Flag::TangentDirection| + MeshVisualizerGL3D::Flag::BitangentFromTangentDirection| + MeshVisualizerGL3D::Flag::NormalDirection} .setViewportSize({80, 80}) /** @todo make this unnecessary */ .draw(sphere); @@ -1346,10 +1346,10 @@ void MeshVisualizerGLTest::renderWireframe2D() { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #ifndef MAGNUM_TARGET_GLES - if(!(data.flags & MeshVisualizer2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(!(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else - if(!(data.flags & MeshVisualizer2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(!(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif @@ -1362,7 +1362,7 @@ void MeshVisualizerGLTest::renderWireframe2D() { const Trade::MeshData circleData = Primitives::circle2DSolid(16); GL::Mesh circle{NoCreate}; - if(data.flags & MeshVisualizer2D::Flag::NoGeometryShader) { + if(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader) { /* Duplicate the vertices. The circle primitive is */ const Trade::MeshData circleDataIndexed = MeshTools::generateIndices(circleData); @@ -1378,11 +1378,11 @@ void MeshVisualizerGLTest::renderWireframe2D() { GL::Buffer vertexId; vertexId.setData(vertexIndex); - circle.addVertexBuffer(std::move(vertexId), 0, MeshVisualizer2D::VertexIndex{}); + circle.addVertexBuffer(std::move(vertexId), 0, MeshVisualizerGL2D::VertexIndex{}); } } else circle = MeshTools::compile(circleData); - MeshVisualizer2D{data.flags|MeshVisualizer2D::Flag::Wireframe} + MeshVisualizerGL2D{data.flags|MeshVisualizerGL2D::Flag::Wireframe} .setColor(0xffff99_rgbf) .setWireframeColor(0x9999ff_rgbf) .setWireframeWidth(data.width) @@ -1398,7 +1398,7 @@ void MeshVisualizerGLTest::renderWireframe2D() { CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found."); { - CORRADE_EXPECT_FAIL_IF(data.flags & MeshVisualizer2D::Flag::NoGeometryShader, + CORRADE_EXPECT_FAIL_IF(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader, "Line width is currently not configurable w/o geometry shader."); #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) /* SwiftShader has differently rasterized edges on four pixels */ @@ -1415,7 +1415,7 @@ void MeshVisualizerGLTest::renderWireframe2D() { } /* Test it's not *too* off, at least */ - if(data.flags & MeshVisualizer2D::Flag::NoGeometryShader) { + if(data.flags & MeshVisualizerGL2D::Flag::NoGeometryShader) { #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) /* SwiftShader has differently rasterized edges on four pixels. Apple A8 on more. */ @@ -1438,10 +1438,10 @@ void MeshVisualizerGLTest::renderWireframe3D() { #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #ifndef MAGNUM_TARGET_GLES - if(!(data.flags & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(!(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else - if(!(data.flags & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(!(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif @@ -1454,7 +1454,7 @@ void MeshVisualizerGLTest::renderWireframe3D() { const Trade::MeshData sphereData = Primitives::icosphereSolid(1); GL::Mesh sphere{NoCreate}; - if(data.flags & MeshVisualizer3D::Flag::NoGeometryShader) { + if(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader) { /* Duplicate the vertices */ sphere = MeshTools::compile(MeshTools::duplicate(sphereData)); @@ -1468,11 +1468,11 @@ void MeshVisualizerGLTest::renderWireframe3D() { GL::Buffer vertexId; vertexId.setData(vertexIndex); - sphere.addVertexBuffer(std::move(vertexId), 0, MeshVisualizer3D::VertexIndex{}); + sphere.addVertexBuffer(std::move(vertexId), 0, MeshVisualizerGL3D::VertexIndex{}); } } else sphere = MeshTools::compile(sphereData); - MeshVisualizer3D{data.flags|MeshVisualizer3D::Flag::Wireframe} + MeshVisualizerGL3D{data.flags|MeshVisualizerGL3D::Flag::Wireframe} .setColor(0xffff99_rgbf) .setWireframeColor(0x9999ff_rgbf) .setWireframeWidth(data.width) @@ -1492,7 +1492,7 @@ void MeshVisualizerGLTest::renderWireframe3D() { CORRADE_SKIP("AnyImageImporter / TgaImporter plugins not found."); { - CORRADE_EXPECT_FAIL_IF(data.flags & MeshVisualizer3D::Flag::NoGeometryShader, + CORRADE_EXPECT_FAIL_IF(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader, "Line width is currently not configurable w/o geometry shader."); #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) /* SwiftShader has differently rasterized edges on four pixels. On a @@ -1500,7 +1500,7 @@ void MeshVisualizerGLTest::renderWireframe3D() { the artifacts are bigger. */ Float maxThreshold = 170.0f, meanThreshold = 0.327f; #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(!(data.flags & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(!(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) meanThreshold = 2.166f; #endif #else @@ -1515,7 +1515,7 @@ void MeshVisualizerGLTest::renderWireframe3D() { } /* Test it's not *too* off, at least */ - if(data.flags & MeshVisualizer3D::Flag::NoGeometryShader) { + if(data.flags & MeshVisualizerGL3D::Flag::NoGeometryShader) { #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) /* SwiftShader has differently rasterized edges on four pixels. Apple A8 on more. */ @@ -1538,17 +1538,17 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D() { setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES - if((data.flags2D & MeshVisualizer2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) + if((data.flags2D & MeshVisualizerGL2D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif /* Interestingly for PrimitiveIdFromVertexId gl_VertexID in SwiftShader works -- maybe it works only for nonindexed triangle draws? */ - if(data.flags2D & MeshVisualizer2D::Flag::VertexId && !GL::Context::current().isExtensionSupported()) + if(data.flags2D & MeshVisualizerGL2D::Flag::VertexId && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP("gl_VertexID not supported"); #ifndef MAGNUM_TARGET_WEBGL - if(data.flags2D & MeshVisualizer2D::Flag::PrimitiveId && !(data.flags2D >= MeshVisualizer2D::Flag::PrimitiveIdFromVertexId) && + if(data.flags2D & MeshVisualizerGL2D::Flag::PrimitiveId && !(data.flags2D >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) && #ifndef MAGNUM_TARGET_GLES !GL::Context::current().isVersionSupported(GL::Version::GL320) #else @@ -1557,17 +1557,17 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D() { ) CORRADE_SKIP("gl_PrimitiveID not supported."); #ifndef MAGNUM_TARGET_GLES - if(data.flags2D & MeshVisualizer2D::Flag::Wireframe && !(data.flags2D & MeshVisualizer2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(data.flags2D & MeshVisualizerGL2D::Flag::Wireframe && !(data.flags2D & MeshVisualizerGL2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else - if(data.flags2D & MeshVisualizer2D::Flag::Wireframe && !(data.flags2D & MeshVisualizer2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(data.flags2D & MeshVisualizerGL2D::Flag::Wireframe && !(data.flags2D & MeshVisualizerGL2D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #endif Trade::MeshData circleData = Primitives::circle2DSolid(16); - if(data.flags2D & MeshVisualizer2D::Flag::InstancedObjectId) { + if(data.flags2D & MeshVisualizerGL2D::Flag::InstancedObjectId) { Containers::Array ids{16}; /* Each two faces share the same ID */ for(std::size_t i = 0; i != ids.size(); ++i) ids[i] = i/2; @@ -1580,10 +1580,10 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D() { /* Duplicate the data if using primitive ID from vertex ID or if geometry shader is disabled */ - if(data.flags2D >= MeshVisualizer2D::Flag::PrimitiveIdFromVertexId) + if(data.flags2D >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId) circleData = MeshTools::generateIndices(circleData); - if(data.flags2D >= MeshVisualizer2D::Flag::PrimitiveIdFromVertexId || - data.flags2D & MeshVisualizer2D::Flag::NoGeometryShader) { + if(data.flags2D >= MeshVisualizerGL2D::Flag::PrimitiveIdFromVertexId || + data.flags2D & MeshVisualizerGL2D::Flag::NoGeometryShader) { if(circleData.primitive() != MeshPrimitive::Triangles) circleData = MeshTools::generateIndices(circleData); circleData = MeshTools::duplicate(circleData); @@ -1591,7 +1591,7 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D() { GL::Mesh circle = MeshTools::compile(circleData); - MeshVisualizer2D shader{data.flags2D}; + MeshVisualizerGL2D shader{data.flags2D}; shader /* Remove blue so it's clear the (wireframe) background and mapped ID colors got mixed */ @@ -1602,13 +1602,13 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId2D() { .bindColorMapTexture(_colorMapTexture); /* OTOH the wireframe color should stay at full channels, not mixed */ - if(data.flags3D & MeshVisualizer3D::Flag::Wireframe) + if(data.flags3D & MeshVisualizerGL3D::Flag::Wireframe) shader.setWireframeColor(0xffffff_rgbf); /* For vertex ID we don't want any repeat/wraparound as that causes disruptions in the gradient and test failures. There's 17 vertices also. */ - if(data.flags2D & MeshVisualizer2D::Flag::VertexId) + if(data.flags2D & MeshVisualizerGL2D::Flag::VertexId) shader.setColorMapTransformation(1.0f, -1.0f/17.0f); /* For object/primitive ID there's no gradient so a wraparound is okay. This should cover the first half of the colormap, in reverse order; for @@ -1638,17 +1638,17 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES - if((data.flags3D & MeshVisualizer3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) + if((data.flags3D & MeshVisualizerGL3D::Flag::InstancedObjectId) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif /* Interestingly for PrimitiveIdFromVertexId gl_VertexID in SwiftShader works -- maybe it works only for nonindexed triangle draws? */ - if(data.flags3D & MeshVisualizer3D::Flag::VertexId && !GL::Context::current().isExtensionSupported()) + if(data.flags3D & MeshVisualizerGL3D::Flag::VertexId && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP("gl_VertexID not supported"); #ifndef MAGNUM_TARGET_WEBGL - if(data.flags3D & MeshVisualizer3D::Flag::PrimitiveId && !(data.flags3D >= MeshVisualizer3D::Flag::PrimitiveIdFromVertexId) && + if(data.flags3D & MeshVisualizerGL3D::Flag::PrimitiveId && !(data.flags3D >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId) && #ifndef MAGNUM_TARGET_GLES !GL::Context::current().isVersionSupported(GL::Version::GL320) #else @@ -1657,17 +1657,17 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { ) CORRADE_SKIP("gl_PrimitiveID not supported."); #ifndef MAGNUM_TARGET_GLES - if(data.flags3D & MeshVisualizer3D::Flag::Wireframe && !(data.flags3D & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(data.flags3D & MeshVisualizerGL3D::Flag::Wireframe && !(data.flags3D & MeshVisualizerGL3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::ARB::geometry_shader4::string() << "is not supported."); #else - if(data.flags3D & MeshVisualizer3D::Flag::Wireframe && !(data.flags3D & MeshVisualizer3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) + if(data.flags3D & MeshVisualizerGL3D::Flag::Wireframe && !(data.flags3D & MeshVisualizerGL3D::Flag::NoGeometryShader) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::geometry_shader::string() << "is not supported."); #endif #endif Trade::MeshData icosphereData = Primitives::icosphereSolid(1); - if(data.flags3D & MeshVisualizer3D::Flag::InstancedObjectId) { + if(data.flags3D & MeshVisualizerGL3D::Flag::InstancedObjectId) { Containers::Array ids{80}; /* Each four faces share the same ID */ for(std::size_t i = 0; i != ids.size(); ++i) ids[i] = i/4; @@ -1680,13 +1680,13 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { /* Duplicate the data if using primitive ID from vertex ID or if geometry shader is disabled */ - if(data.flags3D >= MeshVisualizer3D::Flag::PrimitiveIdFromVertexId || - data.flags3D & MeshVisualizer3D::Flag::NoGeometryShader) + if(data.flags3D >= MeshVisualizerGL3D::Flag::PrimitiveIdFromVertexId || + data.flags3D & MeshVisualizerGL3D::Flag::NoGeometryShader) icosphereData = MeshTools::duplicate(icosphereData); GL::Mesh circle = MeshTools::compile(icosphereData); - MeshVisualizer3D shader{data.flags3D}; + MeshVisualizerGL3D shader{data.flags3D}; shader /* Remove blue so it's clear the wireframe background and mapped ID colors got mixed */ @@ -1701,12 +1701,12 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { .bindColorMapTexture(_colorMapTexture); /* OTOH the wireframe color should stay at full channels, not mixed */ - if(data.flags2D & MeshVisualizer2D::Flag::Wireframe) + if(data.flags2D & MeshVisualizerGL2D::Flag::Wireframe) shader.setWireframeColor(0xffffff_rgbf); /* For vertex ID we don't want any repeat/wraparound as that causes disruptions in the gradient and test failures. There's 42 vertices also. */ - if(data.flags2D & MeshVisualizer2D::Flag::VertexId) + if(data.flags2D & MeshVisualizerGL2D::Flag::VertexId) shader.setColorMapTransformation(1.0f, -1.0f/42.0f); /* For object/primitive ID there's no gradient so a wraparound is okay. This should cover the first half of the colormap, in reverse order; for @@ -1728,7 +1728,7 @@ void MeshVisualizerGLTest::renderObjectVertexPrimitiveId3D() { supported, the artifacts are bigger when wireframe is enabled. */ Float maxThreshold = 138.4f, meanThreshold = 0.279f; #if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) - if(data.flags3D & MeshVisualizer3D::Flag::Wireframe && !GL::Context::current().isExtensionSupported()) { + if(data.flags3D & MeshVisualizerGL3D::Flag::Wireframe && !GL::Context::current().isExtensionSupported()) { /* SwiftShader has a bit more rounding errors */ maxThreshold = 238.0f; meanThreshold = 1.957f; @@ -1754,7 +1754,7 @@ void MeshVisualizerGLTest::renderWireframe3DPerspective() { GL::Mesh plane = MeshTools::compile(Primitives::planeSolid()); - MeshVisualizer3D{MeshVisualizer3D::Flag::Wireframe} + MeshVisualizerGL3D{MeshVisualizerGL3D::Flag::Wireframe} .setWireframeWidth(8.0f) .setWireframeColor(0xff0000_rgbf) .setViewportSize({80, 80}) @@ -1848,26 +1848,26 @@ void MeshVisualizerGLTest::renderTangentBitangentNormal() { GL::Mesh mesh{MeshPrimitive::TriangleStrip}; mesh.setCount(4) .addVertexBuffer(vertices, 0, - Shaders::MeshVisualizer3D::Position{}, + Shaders::MeshVisualizerGL3D::Position{}, sizeof(Vector4), /* conditionally added below */ sizeof(Vector3), /* conditionally added below */ - Shaders::MeshVisualizer3D::Normal{}); - if(data.flags & MeshVisualizer3D::Flag::BitangentFromTangentDirection && !data.skipBitagnentEvenIfEnabledInFlags) + Shaders::MeshVisualizerGL3D::Normal{}); + if(data.flags & MeshVisualizerGL3D::Flag::BitangentFromTangentDirection && !data.skipBitagnentEvenIfEnabledInFlags) mesh.addVertexBuffer(vertices, 0, sizeof(Vector3), - Shaders::MeshVisualizer3D::Tangent4{}, + Shaders::MeshVisualizerGL3D::Tangent4{}, sizeof(Vector3), sizeof(Vector3)); - else if(data.flags & MeshVisualizer3D::Flag::TangentDirection) + else if(data.flags & MeshVisualizerGL3D::Flag::TangentDirection) mesh.addVertexBuffer(vertices, 0, sizeof(Vector3), - Shaders::MeshVisualizer3D::Tangent{}, sizeof(Float), sizeof(Vector3), + Shaders::MeshVisualizerGL3D::Tangent{}, sizeof(Float), sizeof(Vector3), sizeof(Vector3)); - if(data.flags & MeshVisualizer3D::Flag::BitangentDirection && !data.skipBitagnentEvenIfEnabledInFlags) + if(data.flags & MeshVisualizerGL3D::Flag::BitangentDirection && !data.skipBitagnentEvenIfEnabledInFlags) mesh.addVertexBuffer(vertices, 0, sizeof(Vector3), sizeof(Vector4), - Shaders::MeshVisualizer3D::Bitangent{}, + Shaders::MeshVisualizerGL3D::Bitangent{}, sizeof(Vector3)); Matrix4 transformation = Matrix4::translation({0.0f, 0.5f, -3.5f})* @@ -1875,7 +1875,7 @@ void MeshVisualizerGLTest::renderTangentBitangentNormal() { Matrix4::scaling(Vector3::yScale(1.5f)); if(data.secondPassFlags) { - MeshVisualizer3D{data.secondPassFlags} + MeshVisualizerGL3D{data.secondPassFlags} /** @todo make this unnecessary */ .setViewportSize({80, 80}) .setTransformationMatrix(transformation) @@ -1885,7 +1885,7 @@ void MeshVisualizerGLTest::renderTangentBitangentNormal() { .draw(mesh); } - MeshVisualizer3D shader{data.flags}; + MeshVisualizerGL3D shader{data.flags}; shader /** @todo make this unnecessary */ .setViewportSize({80, 80}) @@ -1896,10 +1896,10 @@ void MeshVisualizerGLTest::renderTangentBitangentNormal() { .setLineLength(data.lineLength) .setLineWidth(data.lineWidth); - if(data.flags & MeshVisualizer3D::Flag::Wireframe) shader + if(data.flags & MeshVisualizerGL3D::Flag::Wireframe) shader .setColor(0xffff99_rgbf) .setWireframeColor(0x9999ff_rgbf); - if(data.flags & MeshVisualizer3D::Flag::PrimitiveId) shader + if(data.flags & MeshVisualizerGL3D::Flag::PrimitiveId) shader .bindColorMapTexture(_colorMapTexture) .setColorMapTransformation(1.0f/512.0f, 0.5f); diff --git a/src/Magnum/Shaders/Test/MeshVisualizerGL_Test.cpp b/src/Magnum/Shaders/Test/MeshVisualizerGL_Test.cpp new file mode 100644 index 000000000..acee35225 --- /dev/null +++ b/src/Magnum/Shaders/Test/MeshVisualizerGL_Test.cpp @@ -0,0 +1,145 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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 +#include +#include + +#include "Magnum/Shaders/MeshVisualizerGL.h" + +namespace Magnum { namespace Shaders { namespace Test { namespace { + +/* There's an underscore between GL and Test to disambiguate from GLTest, which + is a common suffix used to mark tests that need a GL context. Ugly, I know. */ +struct MeshVisualizerGL_Test: TestSuite::Tester { + explicit MeshVisualizerGL_Test(); + + void constructNoCreate2D(); + void constructNoCreate3D(); + + void constructCopy2D(); + void constructCopy3D(); + + void vertexIndexSameAsObjectId(); + + void debugFlag2D(); + void debugFlag3D(); + void debugFlags2D(); + void debugFlags3D(); +}; + +MeshVisualizerGL_Test::MeshVisualizerGL_Test() { + addTests({&MeshVisualizerGL_Test::constructNoCreate2D, + &MeshVisualizerGL_Test::constructNoCreate3D, + + &MeshVisualizerGL_Test::constructCopy2D, + &MeshVisualizerGL_Test::constructCopy3D, + + &MeshVisualizerGL_Test::vertexIndexSameAsObjectId, + + &MeshVisualizerGL_Test::debugFlag2D, + &MeshVisualizerGL_Test::debugFlag3D, + &MeshVisualizerGL_Test::debugFlags2D, + &MeshVisualizerGL_Test::debugFlags3D}); +} + +void MeshVisualizerGL_Test::constructNoCreate2D() { + { + MeshVisualizerGL2D shader{NoCreate}; + CORRADE_COMPARE(shader.id(), 0); + CORRADE_COMPARE(shader.flags(), MeshVisualizerGL2D::Flags{}); + } + + CORRADE_VERIFY(true); +} + +void MeshVisualizerGL_Test::constructNoCreate3D() { + { + MeshVisualizerGL3D shader{NoCreate}; + CORRADE_COMPARE(shader.id(), 0); + CORRADE_COMPARE(shader.flags(), MeshVisualizerGL3D::Flags{}); + } + + CORRADE_VERIFY(true); +} + +void MeshVisualizerGL_Test::constructCopy2D() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +void MeshVisualizerGL_Test::constructCopy3D() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); +} + +void MeshVisualizerGL_Test::vertexIndexSameAsObjectId() { + #ifdef MAGNUM_TARGET_GLES2 + CORRADE_SKIP("Object ID is not available on ES2."); + #else + CORRADE_COMPARE(MeshVisualizerGL2D::VertexIndex::Location, GenericGL2D::ObjectId::Location); + CORRADE_COMPARE(MeshVisualizerGL3D::VertexIndex::Location, GenericGL3D::ObjectId::Location); + #endif +} + +void MeshVisualizerGL_Test::debugFlag2D() { + std::ostringstream out; + + Debug{&out} << MeshVisualizerGL2D::Flag::Wireframe << MeshVisualizerGL2D::Flag(0xf0); + CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizerGL2D::Flag::Wireframe Shaders::MeshVisualizerGL2D::Flag(0xf0)\n"); +} + +void MeshVisualizerGL_Test::debugFlag3D() { + std::ostringstream out; + + Debug{&out} << MeshVisualizerGL3D::Flag::Wireframe << MeshVisualizerGL3D::Flag(0xf0); + CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizerGL3D::Flag::Wireframe Shaders::MeshVisualizerGL3D::Flag(0xf0)\n"); +} + +void MeshVisualizerGL_Test::debugFlags2D() { + std::ostringstream out; + + Debug{&out} << (MeshVisualizerGL2D::Flag::Wireframe|MeshVisualizerGL2D::Flag::NoGeometryShader) << MeshVisualizerGL2D::Flags{}; + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizerGL2D::Flag::Wireframe|Shaders::MeshVisualizerGL2D::Flag::NoGeometryShader Shaders::MeshVisualizerGL2D::Flags{}\n"); + #else + CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizerGL2D::Flag::Wireframe Shaders::MeshVisualizerGL2D::Flags{}\n"); + #endif +} + +void MeshVisualizerGL_Test::debugFlags3D() { + std::ostringstream out; + + Debug{&out} << (MeshVisualizerGL3D::Flag::Wireframe|MeshVisualizerGL3D::Flag::NoGeometryShader) << MeshVisualizerGL3D::Flags{}; + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizerGL3D::Flag::Wireframe|Shaders::MeshVisualizerGL3D::Flag::NoGeometryShader Shaders::MeshVisualizerGL3D::Flags{}\n"); + #else + CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizerGL3D::Flag::Wireframe Shaders::MeshVisualizerGL3D::Flags{}\n"); + #endif +} + +}}}} + +CORRADE_TEST_MAIN(Magnum::Shaders::Test::MeshVisualizerGL_Test) diff --git a/src/Magnum/Shaders/Test/MeshVisualizerTest.cpp b/src/Magnum/Shaders/Test/MeshVisualizerTest.cpp deleted file mode 100644 index 7b9ebde52..000000000 --- a/src/Magnum/Shaders/Test/MeshVisualizerTest.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - This file is part of Magnum. - - Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, - 2020, 2021 Vladimír Vondruš - - 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 -#include -#include - -#include "Magnum/Shaders/MeshVisualizer.h" - -namespace Magnum { namespace Shaders { namespace Test { namespace { - -struct MeshVisualizerTest: TestSuite::Tester { - explicit MeshVisualizerTest(); - - void constructNoCreate2D(); - void constructNoCreate3D(); - - void constructCopy2D(); - void constructCopy3D(); - - void vertexIndexSameAsObjectId(); - - void debugFlag2D(); - void debugFlag3D(); - void debugFlags2D(); - void debugFlags3D(); -}; - -MeshVisualizerTest::MeshVisualizerTest() { - addTests({&MeshVisualizerTest::constructNoCreate2D, - &MeshVisualizerTest::constructNoCreate3D, - - &MeshVisualizerTest::constructCopy2D, - &MeshVisualizerTest::constructCopy3D, - - &MeshVisualizerTest::vertexIndexSameAsObjectId, - - &MeshVisualizerTest::debugFlag2D, - &MeshVisualizerTest::debugFlag3D, - &MeshVisualizerTest::debugFlags2D, - &MeshVisualizerTest::debugFlags3D}); -} - -void MeshVisualizerTest::constructNoCreate2D() { - { - MeshVisualizer2D shader{NoCreate}; - CORRADE_COMPARE(shader.id(), 0); - CORRADE_COMPARE(shader.flags(), MeshVisualizer2D::Flags{}); - } - - CORRADE_VERIFY(true); -} - -void MeshVisualizerTest::constructNoCreate3D() { - { - MeshVisualizer3D shader{NoCreate}; - CORRADE_COMPARE(shader.id(), 0); - CORRADE_COMPARE(shader.flags(), MeshVisualizer3D::Flags{}); - } - - CORRADE_VERIFY(true); -} - -void MeshVisualizerTest::constructCopy2D() { - CORRADE_VERIFY(!std::is_copy_constructible{}); - CORRADE_VERIFY(!std::is_copy_assignable{}); -} - -void MeshVisualizerTest::constructCopy3D() { - CORRADE_VERIFY(!std::is_copy_constructible{}); - CORRADE_VERIFY(!std::is_copy_assignable{}); -} - -void MeshVisualizerTest::vertexIndexSameAsObjectId() { - #ifdef MAGNUM_TARGET_GLES2 - CORRADE_SKIP("Object ID is not available on ES2."); - #else - CORRADE_COMPARE(MeshVisualizer2D::VertexIndex::Location, Generic2D::ObjectId::Location); - CORRADE_COMPARE(MeshVisualizer3D::VertexIndex::Location, Generic3D::ObjectId::Location); - #endif -} - -void MeshVisualizerTest::debugFlag2D() { - std::ostringstream out; - - Debug{&out} << MeshVisualizer2D::Flag::Wireframe << MeshVisualizer2D::Flag(0xf0); - CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizer2D::Flag::Wireframe Shaders::MeshVisualizer2D::Flag(0xf0)\n"); -} - -void MeshVisualizerTest::debugFlag3D() { - std::ostringstream out; - - Debug{&out} << MeshVisualizer3D::Flag::Wireframe << MeshVisualizer3D::Flag(0xf0); - CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizer3D::Flag::Wireframe Shaders::MeshVisualizer3D::Flag(0xf0)\n"); -} - -void MeshVisualizerTest::debugFlags2D() { - std::ostringstream out; - - Debug{&out} << (MeshVisualizer2D::Flag::Wireframe|MeshVisualizer2D::Flag::NoGeometryShader) << MeshVisualizer2D::Flags{}; - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizer2D::Flag::Wireframe|Shaders::MeshVisualizer2D::Flag::NoGeometryShader Shaders::MeshVisualizer2D::Flags{}\n"); - #else - CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizer2D::Flag::Wireframe Shaders::MeshVisualizer2D::Flags{}\n"); - #endif -} - -void MeshVisualizerTest::debugFlags3D() { - std::ostringstream out; - - Debug{&out} << (MeshVisualizer3D::Flag::Wireframe|MeshVisualizer3D::Flag::NoGeometryShader) << MeshVisualizer3D::Flags{}; - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizer3D::Flag::Wireframe|Shaders::MeshVisualizer3D::Flag::NoGeometryShader Shaders::MeshVisualizer3D::Flags{}\n"); - #else - CORRADE_COMPARE(out.str(), "Shaders::MeshVisualizer3D::Flag::Wireframe Shaders::MeshVisualizer3D::Flags{}\n"); - #endif -} - -}}}} - -CORRADE_TEST_MAIN(Magnum::Shaders::Test::MeshVisualizerTest) diff --git a/src/Magnum/Shaders/Test/PhongGLTest.cpp b/src/Magnum/Shaders/Test/PhongGLTest.cpp index 8a811c711..1d0d031cb 100644 --- a/src/Magnum/Shaders/Test/PhongGLTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGLTest.cpp @@ -52,7 +52,7 @@ #include "Magnum/MeshTools/Transform.h" #include "Magnum/Primitives/Plane.h" #include "Magnum/Primitives/UVSphere.h" -#include "Magnum/Shaders/Phong.h" +#include "Magnum/Shaders/PhongGL.h" #include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/ImageData.h" #include "Magnum/Trade/MeshData.h" @@ -140,36 +140,36 @@ struct PhongGLTest: GL::OpenGLTester { constexpr struct { const char* name; - Phong::Flags flags; + PhongGL::Flags flags; UnsignedInt lightCount; } ConstructData[]{ {"", {}, 1}, - {"ambient texture", Phong::Flag::AmbientTexture, 1}, - {"diffuse texture", Phong::Flag::DiffuseTexture, 1}, - {"diffuse texture + texture transform", Phong::Flag::DiffuseTexture|Phong::Flag::TextureTransformation, 1}, - {"specular texture", Phong::Flag::SpecularTexture, 1}, - {"normal texture", Phong::Flag::NormalTexture, 1}, - {"normal texture + separate bitangents", Phong::Flag::NormalTexture|Phong::Flag::Bitangent, 1}, - {"separate bitangents alone", Phong::Flag::Bitangent, 1}, - {"ambient + diffuse texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 1}, - {"ambient + specular texture", Phong::Flag::AmbientTexture|Phong::Flag::SpecularTexture, 1}, - {"diffuse + specular texture", Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, 1}, - {"ambient + diffuse + specular texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, 1}, - {"ambient + diffuse + specular + normal texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture|Phong::Flag::NormalTexture, 1}, - {"alpha mask", Phong::Flag::AlphaMask, 1}, - {"alpha mask + diffuse texture", Phong::Flag::AlphaMask|Phong::Flag::DiffuseTexture, 1}, - {"vertex colors", Phong::Flag::VertexColor, 1}, - {"vertex colors + diffuse texture", Phong::Flag::VertexColor|Phong::Flag::DiffuseTexture, 1}, + {"ambient texture", PhongGL::Flag::AmbientTexture, 1}, + {"diffuse texture", PhongGL::Flag::DiffuseTexture, 1}, + {"diffuse texture + texture transform", PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureTransformation, 1}, + {"specular texture", PhongGL::Flag::SpecularTexture, 1}, + {"normal texture", PhongGL::Flag::NormalTexture, 1}, + {"normal texture + separate bitangents", PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent, 1}, + {"separate bitangents alone", PhongGL::Flag::Bitangent, 1}, + {"ambient + diffuse texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture, 1}, + {"ambient + specular texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::SpecularTexture, 1}, + {"diffuse + specular texture", PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, 1}, + {"ambient + diffuse + specular texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, 1}, + {"ambient + diffuse + specular + normal texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture, 1}, + {"alpha mask", PhongGL::Flag::AlphaMask, 1}, + {"alpha mask + diffuse texture", PhongGL::Flag::AlphaMask|PhongGL::Flag::DiffuseTexture, 1}, + {"vertex colors", PhongGL::Flag::VertexColor, 1}, + {"vertex colors + diffuse texture", PhongGL::Flag::VertexColor|PhongGL::Flag::DiffuseTexture, 1}, #ifndef MAGNUM_TARGET_GLES2 - {"object ID", Phong::Flag::ObjectId, 1}, - {"instanced object ID", Phong::Flag::InstancedObjectId, 1}, - {"object ID + alpha mask + specular texture", Phong::Flag::ObjectId|Phong::Flag::AlphaMask|Phong::Flag::SpecularTexture, 1}, + {"object ID", PhongGL::Flag::ObjectId, 1}, + {"instanced object ID", PhongGL::Flag::InstancedObjectId, 1}, + {"object ID + alpha mask + specular texture", PhongGL::Flag::ObjectId|PhongGL::Flag::AlphaMask|PhongGL::Flag::SpecularTexture, 1}, #endif {"five lights", {}, 5}, {"zero lights", {}, 0}, - {"instanced transformation", Phong::Flag::InstancedTransformation, 3}, - {"instanced specular texture offset", Phong::Flag::SpecularTexture|Phong::Flag::InstancedTextureOffset, 3}, - {"instanced normal texture offset", Phong::Flag::NormalTexture|Phong::Flag::InstancedTextureOffset, 3} + {"instanced transformation", PhongGL::Flag::InstancedTransformation, 3}, + {"instanced specular texture offset", PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3}, + {"instanced normal texture offset", PhongGL::Flag::NormalTexture|PhongGL::Flag::InstancedTextureOffset, 3} }; using namespace Math::Literals; @@ -196,17 +196,17 @@ constexpr struct { const struct { const char* name; const char* expected; - Phong::Flags flags; + PhongGL::Flags flags; Matrix3 textureTransformation; } RenderTexturedData[]{ - {"all", "textured.tga", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, {}}, - {"ambient", "textured-ambient.tga", Phong::Flag::AmbientTexture, {}}, - {"diffuse", "textured-diffuse.tga", Phong::Flag::DiffuseTexture, {}}, + {"all", "textured.tga", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, {}}, + {"ambient", "textured-ambient.tga", PhongGL::Flag::AmbientTexture, {}}, + {"diffuse", "textured-diffuse.tga", PhongGL::Flag::DiffuseTexture, {}}, {"diffuse transformed", "textured-diffuse-transformed.tga", - Phong::Flag::DiffuseTexture|Phong::Flag::TextureTransformation, + PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureTransformation, Matrix3::translation(Vector2{1.0f})*Matrix3::scaling(Vector2{-1.0f}) }, - {"specular", "textured-specular.tga", Phong::Flag::SpecularTexture, {}} + {"specular", "textured-specular.tga", PhongGL::Flag::SpecularTexture, {}} }; /* MSVC 2015 doesn't like constexpr here due to the angles */ @@ -218,50 +218,50 @@ const struct { Float scale; Vector4 tangent; Vector3 bitangent; - Shaders::Phong::Tangent4::Components tangentComponents; + PhongGL::Tangent4::Components tangentComponents; bool flipNormalY; - Shaders::Phong::Flags flags; + PhongGL::Flags flags; } RenderTexturedNormalData[]{ {"", "textured-normal.tga", false, {}, 1.0f, {1.0f, 0.0f, 0.0f, 1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, false, {}}, + PhongGL::Tangent4::Components::Four, false, {}}, {"multi bind", "textured-normal.tga", true, {}, 1.0f, {1.0f, 0.0f, 0.0f, 1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, false, {}}, + PhongGL::Tangent4::Components::Four, false, {}}, {"rotated 90°", "textured-normal.tga", false, 90.0_degf, 1.0f, {1.0f, 0.0f, 0.0f, 1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, false, {}}, + PhongGL::Tangent4::Components::Four, false, {}}, {"rotated -90°", "textured-normal.tga", false, -90.0_degf, 1.0f, {1.0f, 0.0f, 0.0f, 1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, false, {}}, + PhongGL::Tangent4::Components::Four, false, {}}, {"0.5 scale", "textured-normal0.5.tga", false, {}, 0.5f, {1.0f, 0.0f, 0.0f, 1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, false, {}}, + PhongGL::Tangent4::Components::Four, false, {}}, {"0.0 scale", "textured-normal0.0.tga", false, {}, 0.0f, {1.0f, 0.0f, 0.0f, 1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, false, {}}, + PhongGL::Tangent4::Components::Four, false, {}}, /* The fourth component, if missing, gets automatically filled up to 1, so this should work */ {"implicit bitangent direction", "textured-normal.tga", false, {}, 1.0f, {1.0f, 0.0f, 0.0f, 0.0f}, {}, - Shaders::Phong::Tangent4::Components::Three, false, {}}, + PhongGL::Tangent4::Components::Three, false, {}}, {"separate bitangents", "textured-normal.tga", false, {}, 1.0f, {1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f}, - Shaders::Phong::Tangent4::Components::Three, false, - Shaders::Phong::Flag::Bitangent}, + PhongGL::Tangent4::Components::Three, false, + PhongGL::Flag::Bitangent}, {"right-handed, flipped Y", "textured-normal-left.tga", false, {}, 1.0f, {1.0f, 0.0f, 0.0f, 1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, true, {}}, + PhongGL::Tangent4::Components::Four, true, {}}, {"left-handed", "textured-normal-left.tga", false, {}, 1.0f, {1.0f, 0.0f, 0.0f, -1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, false, {}}, + PhongGL::Tangent4::Components::Four, false, {}}, {"left-handed, separate bitangents", "textured-normal-left.tga", false, {}, 1.0f, {1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, - Shaders::Phong::Tangent4::Components::Three, false, - Shaders::Phong::Flag::Bitangent}, + PhongGL::Tangent4::Components::Three, false, + PhongGL::Flag::Bitangent}, {"left-handed, flipped Y", "textured-normal.tga", false, {}, 1.0f, {1.0f, 0.0f, 0.0f, -1.0f}, {}, - Shaders::Phong::Tangent4::Components::Four, true, {}} + PhongGL::Tangent4::Components::Four, true, {}} }; const struct { @@ -281,7 +281,7 @@ const struct { const char* name; const char* expected; bool blending; - Phong::Flags flags; + PhongGL::Flags flags; Float threshold; const char* ambientTexture; const char* diffuseTexture; @@ -291,35 +291,35 @@ const struct { /* All those deliberately have a non-white diffuse in order to match the expected data from textured() */ {"none, separate", "PhongTestFiles/textured-diffuse.tga", false, - Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 0.0f, + PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture, 0.0f, "alpha-texture.tga", "diffuse-texture.tga", 0xffffffff_rgbaf, 0x9999ff00_rgbaf}, {"none, combined", "PhongTestFiles/textured-diffuse.tga", false, - Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 0.0f, + PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture, 0.0f, "diffuse-alpha-texture.tga", "diffuse-alpha-texture.tga", 0x000000ff_rgbaf, 0x9999ff00_rgbaf}, {"blending, separate", "PhongTestFiles/textured-diffuse-alpha.tga", true, - Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 0.0f, + PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture, 0.0f, "alpha-texture.tga", "diffuse-texture.tga", 0xffffffff_rgbaf, 0x9999ff00_rgbaf}, {"blending, combined", "PhongTestFiles/textured-diffuse-alpha.tga", true, - Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 0.0f, + PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture, 0.0f, "diffuse-alpha-texture.tga", "diffuse-alpha-texture.tga", 0x000000ff_rgbaf, 0x9999ff00_rgbaf}, {"masking 0.0, separate", "PhongTestFiles/textured-diffuse.tga", false, - Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::AlphaMask, 0.0f, + PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AlphaMask, 0.0f, "alpha-texture.tga", "diffuse-texture.tga", 0xffffffff_rgbaf, 0x9999ff00_rgbaf}, {"masking 0.5, separate", "PhongTestFiles/textured-diffuse-alpha-mask0.5.tga", false, - Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::AlphaMask, 0.5f, + PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AlphaMask, 0.5f, "alpha-texture.tga", "diffuse-texture.tga", 0xffffffff_rgbaf, 0x9999ff00_rgbaf}, {"masking 0.5, combined", "PhongTestFiles/textured-diffuse-alpha-mask0.5.tga", false, - Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::AlphaMask, 0.5f, + PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AlphaMask, 0.5f, "diffuse-alpha-texture.tga", "diffuse-alpha-texture.tga", 0x000000ff_rgbaf, 0x9999ff00_rgbaf}, {"masking 1.0, separate", "TestFiles/alpha-mask1.0.tga", false, - Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::AlphaMask, 1.0f, + PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AlphaMask, 1.0f, "alpha-texture.tga", "diffuse-texture.tga", 0xffffffff_rgbaf, 0x9999ff00_rgbaf} }; @@ -327,17 +327,17 @@ const struct { #ifndef MAGNUM_TARGET_GLES2 constexpr struct { const char* name; - Phong::Flags flags; + PhongGL::Flags flags; UnsignedInt uniformId; UnsignedInt instanceCount; UnsignedInt expected; } RenderObjectIdData[] { {"", /* Verify that it can hold 16 bits at least */ - Phong::Flag::ObjectId, 48526, 0, 48526}, + PhongGL::Flag::ObjectId, 48526, 0, 48526}, {"instanced, first instance", - Phong::Flag::InstancedObjectId, 13524, 1, 24526}, + PhongGL::Flag::InstancedObjectId, 13524, 1, 24526}, {"instanced, second instance", - Phong::Flag::InstancedObjectId, 13524, 2, 62347} + PhongGL::Flag::InstancedObjectId, 13524, 2, 62347} }; #endif @@ -460,7 +460,7 @@ const struct { constexpr struct { const char* name; const char* file; - Phong::Flags flags; + PhongGL::Flags flags; Float maxThreshold, meanThreshold; } RenderInstancedData[] { {"diffuse", "instanced.tga", {}, @@ -472,7 +472,7 @@ constexpr struct { 96.34f, 0.113f, #endif }, - {"diffuse + normal", "instanced-normal.tga", Phong::Flag::NormalTexture, + {"diffuse + normal", "instanced-normal.tga", PhongGL::Flag::NormalTexture, #if !(defined(MAGNUM_TARGET_GLES2) && defined(MAGNUM_TARGET_WEBGL)) /* AMD has one off pixel, llvmpipe more */ 96.0f, 0.333f, @@ -599,11 +599,11 @@ void PhongGLTest::construct() { setTestCaseDescription(data.name); #ifndef MAGNUM_TARGET_GLES - if((data.flags & Phong::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) + if((data.flags & PhongGL::Flag::ObjectId) && !GL::Context::current().isExtensionSupported()) CORRADE_SKIP(GL::Extensions::EXT::gpu_shader4::string() << "is not supported."); #endif - Phong shader{data.flags, data.lightCount}; + PhongGL shader{data.flags, data.lightCount}; CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_COMPARE(shader.lightCount(), data.lightCount); CORRADE_VERIFY(shader.id()); @@ -618,22 +618,22 @@ void PhongGLTest::construct() { } void PhongGLTest::constructMove() { - Phong a{Phong::Flag::AlphaMask, 3}; + PhongGL a{PhongGL::Flag::AlphaMask, 3}; const GLuint id = a.id(); CORRADE_VERIFY(id); MAGNUM_VERIFY_NO_GL_ERROR(); - Phong b{std::move(a)}; + PhongGL b{std::move(a)}; CORRADE_COMPARE(b.id(), id); - CORRADE_COMPARE(b.flags(), Phong::Flag::AlphaMask); + CORRADE_COMPARE(b.flags(), PhongGL::Flag::AlphaMask); CORRADE_COMPARE(b.lightCount(), 3); CORRADE_VERIFY(!a.id()); - Phong c{NoCreate}; + PhongGL c{NoCreate}; c = std::move(b); CORRADE_COMPARE(c.id(), id); - CORRADE_COMPARE(c.flags(), Phong::Flag::AlphaMask); + CORRADE_COMPARE(c.flags(), PhongGL::Flag::AlphaMask); CORRADE_COMPARE(c.lightCount(), 3); CORRADE_VERIFY(!b.id()); } @@ -645,9 +645,9 @@ void PhongGLTest::constructTextureTransformationNotTextured() { std::ostringstream out; Error redirectError{&out}; - Phong{Phong::Flag::TextureTransformation}; + PhongGL{PhongGL::Flag::TextureTransformation}; CORRADE_COMPARE(out.str(), - "Shaders::Phong: texture transformation enabled but the shader is not textured\n"); + "Shaders::PhongGL: texture transformation enabled but the shader is not textured\n"); } void PhongGLTest::bindTexturesNotEnabled() { @@ -659,7 +659,7 @@ void PhongGLTest::bindTexturesNotEnabled() { Error redirectError{&out}; GL::Texture2D texture; - Phong shader; + PhongGL shader; shader.bindAmbientTexture(texture) .bindDiffuseTexture(texture) .bindSpecularTexture(texture) @@ -668,12 +668,12 @@ void PhongGLTest::bindTexturesNotEnabled() { .bindTextures(&texture, &texture, &texture, &texture); CORRADE_COMPARE(out.str(), - "Shaders::Phong::bindAmbientTexture(): the shader was not created with ambient texture enabled\n" - "Shaders::Phong::bindDiffuseTexture(): the shader was not created with diffuse texture enabled\n" - "Shaders::Phong::bindSpecularTexture(): the shader was not created with specular texture enabled\n" - "Shaders::Phong::bindNormalTexture(): the shader was not created with normal texture enabled\n" - "Shaders::Phong::setNormalTextureScale(): the shader was not created with normal texture enabled\n" - "Shaders::Phong::bindTextures(): the shader was not created with any textures enabled\n"); + "Shaders::PhongGL::bindAmbientTexture(): the shader was not created with ambient texture enabled\n" + "Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled\n" + "Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled\n" + "Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled\n" + "Shaders::PhongGL::setNormalTextureScale(): the shader was not created with normal texture enabled\n" + "Shaders::PhongGL::bindTextures(): the shader was not created with any textures enabled\n"); } void PhongGLTest::setAlphaMaskNotEnabled() { @@ -684,11 +684,11 @@ void PhongGLTest::setAlphaMaskNotEnabled() { std::ostringstream out; Error redirectError{&out}; - Phong shader; + PhongGL shader; shader.setAlphaMask(0.75f); CORRADE_COMPARE(out.str(), - "Shaders::Phong::setAlphaMask(): the shader was not created with alpha mask enabled\n"); + "Shaders::PhongGL::setAlphaMask(): the shader was not created with alpha mask enabled\n"); } void PhongGLTest::setTextureMatrixNotEnabled() { @@ -699,11 +699,11 @@ void PhongGLTest::setTextureMatrixNotEnabled() { std::ostringstream out; Error redirectError{&out}; - Phong shader; + PhongGL shader; shader.setTextureMatrix({}); CORRADE_COMPARE(out.str(), - "Shaders::Phong::setTextureMatrix(): the shader was not created with texture transformation enabled\n"); + "Shaders::PhongGL::setTextureMatrix(): the shader was not created with texture transformation enabled\n"); } #ifndef MAGNUM_TARGET_GLES2 @@ -715,11 +715,11 @@ void PhongGLTest::setObjectIdNotEnabled() { std::ostringstream out; Error redirectError{&out}; - Phong shader; + PhongGL shader; shader.setObjectId(33376); CORRADE_COMPARE(out.str(), - "Shaders::Phong::setObjectId(): the shader was not created with object ID enabled\n"); + "Shaders::PhongGL::setObjectId(): the shader was not created with object ID enabled\n"); } #endif @@ -730,14 +730,14 @@ void PhongGLTest::setWrongLightCount() { std::ostringstream out; Error redirectError{&out}; - Phong{{}, 5} + PhongGL{{}, 5} .setLightColors({Color3{}}) .setLightPositions({Vector4{}}) .setLightRanges({0.0f}); CORRADE_COMPARE(out.str(), - "Shaders::Phong::setLightColors(): expected 5 items but got 1\n" - "Shaders::Phong::setLightPositions(): expected 5 items but got 1\n" - "Shaders::Phong::setLightRanges(): expected 5 items but got 1\n"); + "Shaders::PhongGL::setLightColors(): expected 5 items but got 1\n" + "Shaders::PhongGL::setLightPositions(): expected 5 items but got 1\n" + "Shaders::PhongGL::setLightRanges(): expected 5 items but got 1\n"); } void PhongGLTest::setWrongLightId() { @@ -747,14 +747,14 @@ void PhongGLTest::setWrongLightId() { std::ostringstream out; Error redirectError{&out}; - Phong{{}, 3} + PhongGL{{}, 3} .setLightColor(3, Color3{}) .setLightPosition(3, Vector4{}) .setLightRange(3, 0.0f); CORRADE_COMPARE(out.str(), - "Shaders::Phong::setLightColor(): light ID 3 is out of bounds for 3 lights\n" - "Shaders::Phong::setLightPosition(): light ID 3 is out of bounds for 3 lights\n" - "Shaders::Phong::setLightRange(): light ID 3 is out of bounds for 3 lights\n"); + "Shaders::PhongGL::setLightColor(): light ID 3 is out of bounds for 3 lights\n" + "Shaders::PhongGL::setLightPosition(): light ID 3 is out of bounds for 3 lights\n" + "Shaders::PhongGL::setLightRange(): light ID 3 is out of bounds for 3 lights\n"); } constexpr Vector2i RenderSize{80, 80}; @@ -788,7 +788,7 @@ void PhongGLTest::renderTeardown() { void PhongGLTest::renderDefaults() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); - Phong{} + PhongGL{} .draw(sphere); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -818,7 +818,7 @@ void PhongGLTest::renderColored() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); - Phong{{}, 2} + PhongGL{{}, 2} .setLightColors({data.lightColor1, data.lightColor2}) .setLightPositions({{data.lightPosition1, -3.0f, 2.0f, 0.0f}, {data.lightPosition2, -3.0f, 2.0f, 0.0f}}) @@ -901,7 +901,7 @@ void PhongGLTest::renderSinglePixelTextured() { .setStorage(1, TextureFormatRGBA, Vector2i{1}) .setSubImage(0, {}, specularImage); - Phong shader{Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, 2}; + PhongGL shader{PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, 2}; shader.setLightColors({0x993366_rgbf, 0x669933_rgbf}) .setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f}, { 3.0f, -3.0f, 2.0f, 0.0f}}) @@ -949,7 +949,7 @@ void PhongGLTest::renderTextured() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32, Primitives::UVSphereFlag::TextureCoordinates)); - Phong shader{data.flags, 2}; + PhongGL shader{data.flags, 2}; if(data.textureTransformation != Matrix3{}) shader.setTextureMatrix(data.textureTransformation); @@ -958,7 +958,7 @@ void PhongGLTest::renderTextured() { CORRADE_VERIFY(importer); GL::Texture2D ambient; - if(data.flags & Phong::Flag::AmbientTexture) { + if(data.flags & PhongGL::Flag::AmbientTexture) { Containers::Optional image; CORRADE_VERIFY(importer->openFile(Utility::Directory::join(_testDir, "TestFiles/ambient-texture.tga")) && (image = importer->image2D(0))); ambient.setMinificationFilter(GL::SamplerFilter::Linear) @@ -976,7 +976,7 @@ void PhongGLTest::renderTextured() { /* If no diffuse texture is present, dial down the default diffuse color so ambient/specular is visible */ GL::Texture2D diffuse; - if(data.flags & Phong::Flag::DiffuseTexture) { + if(data.flags & PhongGL::Flag::DiffuseTexture) { Containers::Optional image; CORRADE_VERIFY(importer->openFile(Utility::Directory::join(_testDir, "TestFiles/diffuse-texture.tga")) && (image = importer->image2D(0))); diffuse.setMinificationFilter(GL::SamplerFilter::Linear) @@ -992,7 +992,7 @@ void PhongGLTest::renderTextured() { } else shader.setDiffuseColor(0x333333_rgbf); GL::Texture2D specular; - if(data.flags & Phong::Flag::SpecularTexture) { + if(data.flags & PhongGL::Flag::SpecularTexture) { Containers::Optional image; CORRADE_VERIFY(importer->openFile(Utility::Directory::join(_testDir, "TestFiles/specular-texture.tga")) && (image = importer->image2D(0))); specular.setMinificationFilter(GL::SamplerFilter::Linear) @@ -1073,15 +1073,15 @@ void PhongGLTest::renderTexturedNormal() { GL::Buffer tangents; tangents.setData(Containers::Array{DirectInit, 4, tangentBitangent}); plane.addVertexBuffer(tangents, 0, sizeof(TangentBitangent), - GL::DynamicAttribute{Shaders::Phong::Tangent4{data.tangentComponents}}); + GL::DynamicAttribute{Shaders::PhongGL::Tangent4{data.tangentComponents}}); plane.addVertexBuffer(std::move(tangents), sizeof(Vector4), sizeof(TangentBitangent), - GL::DynamicAttribute{Shaders::Phong::Bitangent{}}); + GL::DynamicAttribute{Shaders::PhongGL::Bitangent{}}); /* Rotating the view a few times (together with light positions). If the tangent transformation in the shader is correct, it should result in exactly the same images. */ - Phong shader{Phong::Flag::NormalTexture|data.flags, 2}; + PhongGL shader{PhongGL::Flag::NormalTexture|data.flags, 2}; shader.setLightPositions({ Matrix4::rotationZ(data.rotation)*Vector4{-3.0f, -3.0f, 2.0f, 0.0f}, Matrix4::rotationZ(data.rotation)*Vector4{ 3.0f, -3.0f, 2.0f, 0.0f}}) @@ -1157,7 +1157,7 @@ template void PhongGLTest::renderVertexColor() { GL::Buffer colors; colors.setData(colorData); GL::Mesh sphere = MeshTools::compile(sphereData); - sphere.addVertexBuffer(colors, 0, GL::Attribute{}); + sphere.addVertexBuffer(colors, 0, GL::Attribute{}); Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); CORRADE_VERIFY(importer); @@ -1171,7 +1171,7 @@ template void PhongGLTest::renderVertexColor() { .setStorage(1, TextureFormatRGB, image->size()) .setSubImage(0, {}, *image); - Phong{Phong::Flag::DiffuseTexture|Phong::Flag::VertexColor, 2} + PhongGL{PhongGL::Flag::DiffuseTexture|PhongGL::Flag::VertexColor, 2} .setLightPositions({{-3.0f, -3.0f, 0.0f, 0.0f}, { 3.0f, -3.0f, 0.0f, 0.0f}}) .setTransformationMatrix( @@ -1209,7 +1209,7 @@ void PhongGLTest::renderShininess() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); - Phong{} + PhongGL{} .setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f}}) .setDiffuseColor(0xff3333_rgbf) .setSpecularColor(data.specular) @@ -1343,7 +1343,7 @@ void PhongGLTest::renderAlpha() { GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32, Primitives::UVSphereFlag::TextureCoordinates)); - Phong shader{data.flags, 2}; + PhongGL shader{data.flags, 2}; shader.setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f}, { 3.0f, -3.0f, 2.0f, 0.0f}}) .setTransformationMatrix( @@ -1360,7 +1360,7 @@ void PhongGLTest::renderAlpha() { /* Test that the default is correct by not setting the threshold if it's equal to the default */ - if(data.flags & Phong::Flag::AlphaMask && data.threshold != 0.5f) + if(data.flags & PhongGL::Flag::AlphaMask && data.threshold != 0.5f) shader.setAlphaMask(data.threshold); /* For proper Z order draw back faces first and then front faces */ @@ -1413,8 +1413,8 @@ void PhongGLTest::renderObjectIdSetup() { _objectId.setStorage(GL::RenderbufferFormat::R32UI, RenderSize); _framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{1}, _objectId) .mapForDraw({ - {Phong::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, - {Phong::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}} + {PhongGL::ColorOutput, GL::Framebuffer::ColorAttachment{0}}, + {PhongGL::ObjectIdOutput, GL::Framebuffer::ColorAttachment{1}} }) .clearColor(1, Vector4ui{27}); } @@ -1443,9 +1443,9 @@ void PhongGLTest::renderObjectId() { .setInstanceCount(data.instanceCount) .addVertexBufferInstanced( GL::Buffer{Containers::arrayView({11002u, 48823u})}, - 1, 0, Phong::ObjectId{}); + 1, 0, PhongGL::ObjectId{}); - Phong{data.flags, 2} + PhongGL{data.flags, 2} .setLightColors({0x993366_rgbf, 0x669933_rgbf}) .setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f}, { 3.0f, -3.0f, 2.0f, 0.0f}}) @@ -1502,7 +1502,7 @@ void PhongGLTest::renderLights() { Matrix4 transformation = Matrix4::translation({0.0f, 0.0f, -1.5f}); - Phong{{}, 1} + PhongGL{{}, 1} /* Set non-black ambient to catch accidental NaNs -- the render should never be fully black */ .setAmbientColor(0x222222_rgbf) @@ -1553,7 +1553,7 @@ void PhongGLTest::renderLightsSetOneByOne() { Matrix4 transformation = Matrix4::translation({0.0f, 0.0f, -1.5f}); - Phong{{}, 2} + PhongGL{{}, 2} /* Set non-black ambient to catch accidental NaNs -- the render should never be fully black */ .setAmbientColor(0x222222_rgbf) @@ -1608,7 +1608,7 @@ void PhongGLTest::renderLowLightAngle() { in the vertex shader, where the incorrect normalization caused the fragment-interpolated light direction being incorrect, most visible with long polygons and low light angles. */ - Phong{{}, 1} + PhongGL{{}, 1} .setLightPositions({{0.0f, 0.1f, 0.0f, 1.0f}}) .setShininess(200) .setTransformationMatrix(transformation) @@ -1646,16 +1646,16 @@ void PhongGLTest::renderZeroLights() { Primitives::UVSphereFlag::TextureCoordinates)); /* Enable also Object ID, if supported */ - Phong::Flags flags = Phong::Flag::AmbientTexture|Phong::Flag::NormalTexture|Phong::Flag::AlphaMask; + PhongGL::Flags flags = PhongGL::Flag::AmbientTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::AlphaMask; #ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES if(GL::Context::current().isExtensionSupported()) #endif { - flags |= Phong::Flag::ObjectId; + flags |= PhongGL::Flag::ObjectId; } #endif - Phong shader{flags, 0}; + PhongGL shader{flags, 0}; Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); CORRADE_VERIFY(importer); @@ -1796,10 +1796,10 @@ void PhongGLTest::renderInstanced() { sphere .addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0, - Phong::TransformationMatrix{}, - Phong::NormalMatrix{}, - Phong::Color3{}, - Phong::TextureOffset{}) + PhongGL::TransformationMatrix{}, + PhongGL::NormalMatrix{}, + PhongGL::Color3{}, + PhongGL::TextureOffset{}) .setInstanceCount(3); Containers::Pointer importer = _manager.loadAndInstantiate("AnyImageImporter"); @@ -1822,10 +1822,10 @@ void PhongGLTest::renderInstanced() { .setStorage(1, TextureFormatRGB, image->size()) .setSubImage(0, {}, *image); - Phong shader{Phong::Flag::DiffuseTexture| - Phong::Flag::VertexColor| - Phong::Flag::InstancedTransformation| - Phong::Flag::InstancedTextureOffset|data.flags, 2}; + PhongGL shader{PhongGL::Flag::DiffuseTexture| + PhongGL::Flag::VertexColor| + PhongGL::Flag::InstancedTransformation| + PhongGL::Flag::InstancedTextureOffset|data.flags, 2}; shader .setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f}, { 3.0f, -3.0f, 2.0f, 0.0f}}) @@ -1842,7 +1842,7 @@ void PhongGLTest::renderInstanced() { .bindDiffuseTexture(diffuse) .setDiffuseColor(0xffff99_rgbf); - if(data.flags & Phong::Flag::NormalTexture) + if(data.flags & PhongGL::Flag::NormalTexture) shader.bindNormalTexture(normal); shader.draw(sphere); diff --git a/src/Magnum/Shaders/Test/PhongTest.cpp b/src/Magnum/Shaders/Test/PhongGL_Test.cpp similarity index 54% rename from src/Magnum/Shaders/Test/PhongTest.cpp rename to src/Magnum/Shaders/Test/PhongGL_Test.cpp index 6fbf55df1..b76638f6c 100644 --- a/src/Magnum/Shaders/Test/PhongTest.cpp +++ b/src/Magnum/Shaders/Test/PhongGL_Test.cpp @@ -27,12 +27,14 @@ #include #include -#include "Magnum/Shaders/Phong.h" +#include "Magnum/Shaders/PhongGL.h" namespace Magnum { namespace Shaders { namespace Test { namespace { -struct PhongTest: TestSuite::Tester { - explicit PhongTest(); +/* There's an underscore between GL and Test to disambiguate from GLTest, which + is a common suffix used to mark tests that need a GL context. Ugly, I know. */ +struct PhongGL_Test: TestSuite::Tester { + explicit PhongGL_Test(); void constructNoCreate(); void constructCopy(); @@ -42,63 +44,63 @@ struct PhongTest: TestSuite::Tester { void debugFlagsSupersets(); }; -PhongTest::PhongTest() { - addTests({&PhongTest::constructNoCreate, - &PhongTest::constructCopy, +PhongGL_Test::PhongGL_Test() { + addTests({&PhongGL_Test::constructNoCreate, + &PhongGL_Test::constructCopy, - &PhongTest::debugFlag, - &PhongTest::debugFlags, - &PhongTest::debugFlagsSupersets}); + &PhongGL_Test::debugFlag, + &PhongGL_Test::debugFlags, + &PhongGL_Test::debugFlagsSupersets}); } -void PhongTest::constructNoCreate() { +void PhongGL_Test::constructNoCreate() { { - Phong shader{NoCreate}; + PhongGL shader{NoCreate}; CORRADE_COMPARE(shader.id(), 0); - CORRADE_COMPARE(shader.flags(), Phong::Flags{}); + CORRADE_COMPARE(shader.flags(), PhongGL::Flags{}); CORRADE_COMPARE(shader.lightCount(), 0); } CORRADE_VERIFY(true); } -void PhongTest::constructCopy() { - CORRADE_VERIFY(!std::is_copy_constructible{}); - CORRADE_VERIFY(!std::is_copy_assignable{}); +void PhongGL_Test::constructCopy() { + CORRADE_VERIFY(!std::is_copy_constructible{}); + CORRADE_VERIFY(!std::is_copy_assignable{}); } -void PhongTest::debugFlag() { +void PhongGL_Test::debugFlag() { std::ostringstream out; - Debug{&out} << Phong::Flag::AmbientTexture << Phong::Flag(0xf0); - CORRADE_COMPARE(out.str(), "Shaders::Phong::Flag::AmbientTexture Shaders::Phong::Flag(0xf0)\n"); + Debug{&out} << PhongGL::Flag::AmbientTexture << PhongGL::Flag(0xf0); + CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::AmbientTexture Shaders::PhongGL::Flag(0xf0)\n"); } -void PhongTest::debugFlags() { +void PhongGL_Test::debugFlags() { std::ostringstream out; - Debug{&out} << (Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture) << Phong::Flags{}; - CORRADE_COMPARE(out.str(), "Shaders::Phong::Flag::DiffuseTexture|Shaders::Phong::Flag::SpecularTexture Shaders::Phong::Flags{}\n"); + Debug{&out} << (PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture) << PhongGL::Flags{}; + CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::DiffuseTexture|Shaders::PhongGL::Flag::SpecularTexture Shaders::PhongGL::Flags{}\n"); } -void PhongTest::debugFlagsSupersets() { +void PhongGL_Test::debugFlagsSupersets() { #ifndef MAGNUM_TARGET_GLES2 /* InstancedObjectId is a superset of ObjectId so only one should be printed */ { std::ostringstream out; - Debug{&out} << (Phong::Flag::ObjectId|Phong::Flag::InstancedObjectId); - CORRADE_COMPARE(out.str(), "Shaders::Phong::Flag::InstancedObjectId\n"); + Debug{&out} << (PhongGL::Flag::ObjectId|PhongGL::Flag::InstancedObjectId); + CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::InstancedObjectId\n"); } #endif /* InstancedTextureOffset is a superset of TextureTransformation so only one should be printed */ std::ostringstream out; - Debug{&out} << (Phong::Flag::InstancedTextureOffset|Phong::Flag::TextureTransformation); - CORRADE_COMPARE(out.str(), "Shaders::Phong::Flag::InstancedTextureOffset\n"); + Debug{&out} << (PhongGL::Flag::InstancedTextureOffset|PhongGL::Flag::TextureTransformation); + CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::InstancedTextureOffset\n"); } }}}} -CORRADE_TEST_MAIN(Magnum::Shaders::Test::PhongTest) +CORRADE_TEST_MAIN(Magnum::Shaders::Test::PhongGL_Test) diff --git a/src/Magnum/Shaders/Test/VectorGLTest.cpp b/src/Magnum/Shaders/Test/VectorGLTest.cpp index 83d20eb0a..581281b6c 100644 --- a/src/Magnum/Shaders/Test/VectorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VectorGLTest.cpp @@ -47,7 +47,7 @@ #include "Magnum/MeshTools/Compile.h" #include "Magnum/Primitives/Plane.h" #include "Magnum/Primitives/Square.h" -#include "Magnum/Shaders/Vector.h" +#include "Magnum/Shaders/VectorGL.h" #include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/ImageData.h" #include "Magnum/Trade/MeshData.h" @@ -99,22 +99,22 @@ using namespace Math::Literals; constexpr struct { const char* name; - Vector2D::Flags flags; + VectorGL2D::Flags flags; } ConstructData[]{ {"", {}}, - {"texture transformation", Vector2D::Flag::TextureTransformation} + {"texture transformation", VectorGL2D::Flag::TextureTransformation} }; const struct { const char* name; - Vector2D::Flags flags; + VectorGL2D::Flags flags; Matrix3 textureTransformation; Color4 backgroundColor, color; const char* file2D; const char* file3D; bool flip; } RenderData[] { - {"texture transformation", Vector2D::Flag::TextureTransformation, + {"texture transformation", VectorGL2D::Flag::TextureTransformation, Matrix3::translation(Vector2{1.0f})*Matrix3::scaling(Vector2{-1.0f}), 0x00000000_rgbaf, 0xffffff_rgbf, "defaults.tga", "defaults.tga", true}, @@ -176,7 +176,7 @@ template void VectorGLTest::construct() { auto&& data = ConstructData[testCaseInstanceId()]; setTestCaseDescription(data.name); - Vector shader{data.flags}; + VectorGL shader{data.flags}; CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_VERIFY(shader.id()); { @@ -192,21 +192,21 @@ template void VectorGLTest::construct() { template void VectorGLTest::constructMove() { setTestCaseTemplateName(std::to_string(dimensions)); - Vector a{Vector::Flag::TextureTransformation}; + VectorGL a{VectorGL::Flag::TextureTransformation}; const GLuint id = a.id(); CORRADE_VERIFY(id); MAGNUM_VERIFY_NO_GL_ERROR(); - Vector b{std::move(a)}; + VectorGL b{std::move(a)}; CORRADE_COMPARE(b.id(), id); - CORRADE_COMPARE(b.flags(), Vector::Flag::TextureTransformation); + CORRADE_COMPARE(b.flags(), VectorGL::Flag::TextureTransformation); CORRADE_VERIFY(!a.id()); - Vector c{NoCreate}; + VectorGL c{NoCreate}; c = std::move(b); CORRADE_COMPARE(c.id(), id); - CORRADE_COMPARE(c.flags(), Vector::Flag::TextureTransformation); + CORRADE_COMPARE(c.flags(), VectorGL::Flag::TextureTransformation); CORRADE_VERIFY(!b.id()); } @@ -220,11 +220,11 @@ template void VectorGLTest::setTextureMatrixNotEnabled() std::ostringstream out; Error redirectError{&out}; - Vector shader; + VectorGL shader; shader.setTextureMatrix({}); CORRADE_COMPARE(out.str(), - "Shaders::Vector::setTextureMatrix(): the shader was not created with texture transformation enabled\n"); + "Shaders::VectorGL::setTextureMatrix(): the shader was not created with texture transformation enabled\n"); } constexpr Vector2i RenderSize{80, 80}; @@ -288,7 +288,7 @@ void VectorGLTest::renderDefaults2D() { .setSubImage(0, {}, *image); #endif - Vector2D{} + VectorGL2D{} .bindVectorTexture(texture) .draw(square); @@ -335,7 +335,7 @@ void VectorGLTest::renderDefaults3D() { .setSubImage(0, {}, *image); #endif - Vector3D{} + VectorGL3D{} .bindVectorTexture(texture) .draw(plane); @@ -385,7 +385,7 @@ void VectorGLTest::render2D() { .setSubImage(0, {}, *image); #endif - Vector2D shader{data.flags}; + VectorGL2D shader{data.flags}; shader.setBackgroundColor(data.backgroundColor) .setColor(data.color) .bindVectorTexture(texture); @@ -447,7 +447,7 @@ void VectorGLTest::render3D() { .setSubImage(0, {}, *image); #endif - Vector3D shader{data.flags}; + VectorGL3D shader{data.flags}; shader.setBackgroundColor(data.backgroundColor) .setColor(data.color) .bindVectorTexture(texture); diff --git a/src/Magnum/Shaders/Test/VectorTest.cpp b/src/Magnum/Shaders/Test/VectorGL_Test.cpp similarity index 54% rename from src/Magnum/Shaders/Test/VectorTest.cpp rename to src/Magnum/Shaders/Test/VectorGL_Test.cpp index e6374d79f..ff8e7f2e6 100644 --- a/src/Magnum/Shaders/Test/VectorTest.cpp +++ b/src/Magnum/Shaders/Test/VectorGL_Test.cpp @@ -27,12 +27,14 @@ #include #include -#include "Magnum/Shaders/Vector.h" +#include "Magnum/Shaders/VectorGL.h" namespace Magnum { namespace Shaders { namespace Test { namespace { -struct VectorTest: TestSuite::Tester { - explicit VectorTest(); +/* There's an underscore between GL and Test to disambiguate from GLTest, which + is a common suffix used to mark tests that need a GL context. Ugly, I know. */ +struct VectorGL_Test: TestSuite::Tester { + explicit VectorGL_Test(); template void constructNoCreate(); template void constructCopy(); @@ -41,50 +43,50 @@ struct VectorTest: TestSuite::Tester { void debugFlags(); }; -VectorTest::VectorTest() { - addTests({&VectorTest::constructNoCreate<2>, - &VectorTest::constructNoCreate<3>, +VectorGL_Test::VectorGL_Test() { + addTests({&VectorGL_Test::constructNoCreate<2>, + &VectorGL_Test::constructNoCreate<3>, - &VectorTest::constructCopy<2>, - &VectorTest::constructCopy<3>, + &VectorGL_Test::constructCopy<2>, + &VectorGL_Test::constructCopy<3>, - &VectorTest::debugFlag, - &VectorTest::debugFlags}); + &VectorGL_Test::debugFlag, + &VectorGL_Test::debugFlags}); } -template void VectorTest::constructNoCreate() { +template void VectorGL_Test::constructNoCreate() { setTestCaseTemplateName(std::to_string(dimensions)); { - Vector shader{NoCreate}; + VectorGL shader{NoCreate}; CORRADE_COMPARE(shader.id(), 0); - CORRADE_COMPARE(shader.flags(), typename Vector::Flags{}); + CORRADE_COMPARE(shader.flags(), typename VectorGL::Flags{}); } CORRADE_VERIFY(true); } -template void VectorTest::constructCopy() { +template void VectorGL_Test::constructCopy() { setTestCaseTemplateName(std::to_string(dimensions)); - CORRADE_VERIFY(!std::is_copy_constructible>{}); - CORRADE_VERIFY(!std::is_copy_assignable>{}); + CORRADE_VERIFY(!std::is_copy_constructible>{}); + CORRADE_VERIFY(!std::is_copy_assignable>{}); } -void VectorTest::debugFlag() { +void VectorGL_Test::debugFlag() { std::ostringstream out; - Debug{&out} << Vector2D::Flag::TextureTransformation << Vector2D::Flag(0xf0); - CORRADE_COMPARE(out.str(), "Shaders::Vector::Flag::TextureTransformation Shaders::Vector::Flag(0xf0)\n"); + Debug{&out} << VectorGL2D::Flag::TextureTransformation << VectorGL2D::Flag(0xf0); + CORRADE_COMPARE(out.str(), "Shaders::VectorGL::Flag::TextureTransformation Shaders::VectorGL::Flag(0xf0)\n"); } -void VectorTest::debugFlags() { +void VectorGL_Test::debugFlags() { std::ostringstream out; - Debug{&out} << Vector3D::Flags{Vector3D::Flag::TextureTransformation|Vector3D::Flag(0xf0)} << Vector3D::Flags{}; - CORRADE_COMPARE(out.str(), "Shaders::Vector::Flag::TextureTransformation|Shaders::Vector::Flag(0xf0) Shaders::Vector::Flags{}\n"); + Debug{&out} << VectorGL3D::Flags{VectorGL3D::Flag::TextureTransformation|VectorGL3D::Flag(0xf0)} << VectorGL3D::Flags{}; + CORRADE_COMPARE(out.str(), "Shaders::VectorGL::Flag::TextureTransformation|Shaders::VectorGL::Flag(0xf0) Shaders::VectorGL::Flags{}\n"); } }}}} -CORRADE_TEST_MAIN(Magnum::Shaders::Test::VectorTest) +CORRADE_TEST_MAIN(Magnum::Shaders::Test::VectorGL_Test) diff --git a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp index 8740beb6f..d0e73cbd6 100644 --- a/src/Magnum/Shaders/Test/VertexColorGLTest.cpp +++ b/src/Magnum/Shaders/Test/VertexColorGLTest.cpp @@ -42,7 +42,7 @@ #include "Magnum/MeshTools/Compile.h" #include "Magnum/Primitives/Circle.h" #include "Magnum/Primitives/UVSphere.h" -#include "Magnum/Shaders/VertexColor.h" +#include "Magnum/Shaders/VertexColorGL.h" #include "Magnum/Trade/AbstractImporter.h" #include "Magnum/Trade/MeshData.h" @@ -135,7 +135,7 @@ VertexColorGLTest::VertexColorGLTest() { template void VertexColorGLTest::construct() { setTestCaseTemplateName(std::to_string(dimensions)); - VertexColor shader; + VertexColorGL shader; CORRADE_VERIFY(shader.id()); { #ifdef CORRADE_TARGET_APPLE @@ -150,17 +150,17 @@ template void VertexColorGLTest::construct() { template void VertexColorGLTest::constructMove() { setTestCaseTemplateName(std::to_string(dimensions)); - VertexColor a; + VertexColorGL a; const GLuint id = a.id(); CORRADE_VERIFY(id); MAGNUM_VERIFY_NO_GL_ERROR(); - VertexColor b{std::move(a)}; + VertexColorGL b{std::move(a)}; CORRADE_COMPARE(b.id(), id); CORRADE_VERIFY(!a.id()); - VertexColor c{NoCreate}; + VertexColorGL c{NoCreate}; c = std::move(b); CORRADE_COMPARE(c.id(), id); CORRADE_VERIFY(!b.id()); @@ -205,9 +205,9 @@ template void VertexColorGLTest::renderDefaults2D() { GL::Buffer colors; colors.setData(colorData); GL::Mesh circle = MeshTools::compile(circleData); - circle.addVertexBuffer(colors, 0, GL::Attribute{}); + circle.addVertexBuffer(colors, 0, GL::Attribute{}); - VertexColor2D{} + VertexColorGL2D{} .draw(circle); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -246,9 +246,9 @@ template void VertexColorGLTest::renderDefaults3D() { GL::Buffer colors; colors.setData(colorData); GL::Mesh sphere = MeshTools::compile(sphereData); - sphere.addVertexBuffer(colors, 0, GL::Attribute{}); + sphere.addVertexBuffer(colors, 0, GL::Attribute{}); - VertexColor3D{} + VertexColorGL3D{} .draw(sphere); MAGNUM_VERIFY_NO_GL_ERROR(); @@ -281,9 +281,9 @@ template void VertexColorGLTest::render2D() { GL::Buffer colors; colors.setData(colorData); GL::Mesh circle = MeshTools::compile(circleData); - circle.addVertexBuffer(colors, 0, GL::Attribute{}); + circle.addVertexBuffer(colors, 0, GL::Attribute{}); - VertexColor2D{} + VertexColorGL2D{} .setTransformationProjectionMatrix(Matrix3::projection({2.1f, 2.1f})) .draw(circle); @@ -326,9 +326,9 @@ template void VertexColorGLTest::render3D() { GL::Buffer colors; colors.setData(colorData); GL::Mesh sphere = MeshTools::compile(sphereData); - sphere.addVertexBuffer(colors, 0, GL::Attribute{}); + sphere.addVertexBuffer(colors, 0, GL::Attribute{}); - VertexColor3D{} + VertexColorGL3D{} .setTransformationProjectionMatrix( Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)* Matrix4::translation(Vector3::zAxis(-2.15f))* diff --git a/src/Magnum/Shaders/Test/VertexColorTest.cpp b/src/Magnum/Shaders/Test/VertexColorGL_Test.cpp similarity index 63% rename from src/Magnum/Shaders/Test/VertexColorTest.cpp rename to src/Magnum/Shaders/Test/VertexColorGL_Test.cpp index 630dd37d4..34a8b27d9 100644 --- a/src/Magnum/Shaders/Test/VertexColorTest.cpp +++ b/src/Magnum/Shaders/Test/VertexColorGL_Test.cpp @@ -25,44 +25,46 @@ #include -#include "Magnum/Shaders/VertexColor.h" +#include "Magnum/Shaders/VertexColorGL.h" namespace Magnum { namespace Shaders { namespace Test { namespace { -struct VertexColorTest: TestSuite::Tester { - explicit VertexColorTest(); +/* There's an underscore between GL and Test to disambiguate from GLTest, which + is a common suffix used to mark tests that need a GL context. Ugly, I know. */ +struct VertexColorGL_Test: TestSuite::Tester { + explicit VertexColorGL_Test(); template void constructNoCreate(); template void constructCopy(); }; -VertexColorTest::VertexColorTest() { - addTests({ - &VertexColorTest::constructNoCreate<2>, - &VertexColorTest::constructNoCreate<3>, +VertexColorGL_Test::VertexColorGL_Test() { + addTests({ + &VertexColorGL_Test::constructNoCreate<2>, + &VertexColorGL_Test::constructNoCreate<3>, - &VertexColorTest::constructCopy<2>, - &VertexColorTest::constructCopy<3>}); + &VertexColorGL_Test::constructCopy<2>, + &VertexColorGL_Test::constructCopy<3>}); } -template void VertexColorTest::constructNoCreate() { +template void VertexColorGL_Test::constructNoCreate() { setTestCaseTemplateName(std::to_string(dimensions)); { - VertexColor shader{NoCreate}; + VertexColorGL shader{NoCreate}; CORRADE_COMPARE(shader.id(), 0); } CORRADE_VERIFY(true); } -template void VertexColorTest::constructCopy() { +template void VertexColorGL_Test::constructCopy() { setTestCaseTemplateName(std::to_string(dimensions)); - CORRADE_VERIFY(!std::is_copy_constructible>{}); - CORRADE_VERIFY(!std::is_copy_assignable>{}); + CORRADE_VERIFY(!std::is_copy_constructible>{}); + CORRADE_VERIFY(!std::is_copy_assignable>{}); } }}}} -CORRADE_TEST_MAIN(Magnum::Shaders::Test::VertexColorTest) +CORRADE_TEST_MAIN(Magnum::Shaders::Test::VertexColorGL_Test) diff --git a/src/Magnum/Shaders/Vector.h b/src/Magnum/Shaders/Vector.h index e29d93c2a..e73d13435 100644 --- a/src/Magnum/Shaders/Vector.h +++ b/src/Magnum/Shaders/Vector.h @@ -25,210 +25,46 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file - * @brief Class @ref Magnum::Shaders::Vector, typedef @ref Magnum::Shaders::Vector2D, @ref Magnum::Shaders::Vector3D + * @brief Typedef @ref Magnum::Shaders::Vector, alias @ref Magnum::Shaders::Vector2D, @ref Magnum::Shaders::Vector3D + * @m_deprecated_since_latest Use @ref Magnum/Shaders/VectorGL.h, the + * @ref Magnum::Shaders::VectorGL "VectorGL" class and + * related typedefs instead. */ +#endif -#include "Magnum/DimensionTraits.h" -#include "Magnum/Shaders/AbstractVector.h" -#include "Magnum/Shaders/visibility.h" - -namespace Magnum { namespace Shaders { - -namespace Implementation { - enum class VectorFlag: UnsignedByte { - TextureTransformation = 1 << 0 - }; - typedef Containers::EnumSet VectorFlags; -} - -/** -@brief Vector shader - -Renders vector art in plain grayscale form. See also @ref DistanceFieldVector -for more advanced effects. For rendering an unchanged texture you can use the -@ref Flat shader. You need to provide the @ref Position and -@ref TextureCoordinates attributes in your triangle mesh and call at least -@ref bindVectorTexture(). By default, the shader renders the texture with a -white color in an identity transformation. Use -@ref setTransformationProjectionMatrix(), @ref setColor() and others to -configure the shader. - -@image html shaders-vector.png width=256px - -Alpha / transparency is supported by the shader implicitly, but to have it -working on the framebuffer, you need to enable -@ref GL::Renderer::Feature::Blending and set up the blending function. See -@ref GL::Renderer::setBlendFunction() for details. - -@section Shaders-Vector-usage Example usage - -Common mesh setup: - -@snippet MagnumShaders.cpp Vector-usage1 - -Common rendering setup: - -@snippet MagnumShaders.cpp Vector-usage2 - -@see @ref shaders, @ref Vector2D, @ref Vector3D -*/ -template class MAGNUM_SHADERS_EXPORT Vector: public AbstractVector { - public: - #ifdef DOXYGEN_GENERATING_OUTPUT - /** - * @brief Flag - * @m_since{2020,06} - * - * @see @ref Flags, @ref flags() - */ - enum class Flag: UnsignedByte { - /** - * Enable texture coordinate transformation. - * @see @ref setTextureMatrix() - * @m_since{2020,06} - */ - TextureTransformation = 1 << 0 - }; - - /** - * @brief Flags - * @m_since{2020,06} - * - * @see @ref flags() - */ - typedef Containers::EnumSet Flags; - #else - /* Done this way to be prepared for possible future diversion of 2D - and 3D flags (e.g. introducing 3D-specific features) */ - typedef Implementation::VectorFlag Flag; - typedef Implementation::VectorFlags Flags; - #endif - - /** - * @brief Constructor - * @param flags Flags - */ - explicit Vector(Flags flags = {}); - - /** - * @brief Construct without creating the underlying OpenGL object - * - * The constructed instance is equivalent to a moved-from state. Useful - * in cases where you will overwrite the instance later anyway. Move - * another object over it to make it useful. - * - * This function can be safely used for constructing (and later - * destructing) objects even without any OpenGL context being active. - * However note that this is a low-level and a potentially dangerous - * API, see the documentation of @ref NoCreate for alternatives. - */ - explicit Vector(NoCreateT) noexcept - /** @todoc remove workaround when doxygen is sane */ - #ifndef DOXYGEN_GENERATING_OUTPUT - : AbstractVector{NoCreate} - #endif - {} - - /** @brief Copying is not allowed */ - Vector(const Vector&) = delete; - - /** @brief Move constructor */ - Vector(Vector&&) noexcept = default; - - /** @brief Copying is not allowed */ - Vector& operator=(const Vector&) = delete; - - /** @brief Move assignment */ - Vector& operator=(Vector&&) noexcept = default; - - /** - * @brief Flags - * @m_since{2020,06} - */ - Flags flags() const { return _flags; } - - /** - * @brief Set transformation and projection matrix - * @return Reference to self (for method chaining) - * - * Default is an identity matrix. - */ - Vector& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); - - /** - * @brief Set texture coordinate transformation matrix - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * Expects that the shader was created with - * @ref Flag::TextureTransformation enabled. Initial value is an - * identity matrix. - */ - Vector& setTextureMatrix(const Matrix3& matrix); - - /** - * @brief Set background color - * @return Reference to self (for method chaining) - * - * Default is @cpp 0x00000000_rgbaf @ce. - * @see @ref setColor() - */ - Vector& setBackgroundColor(const Color4& color); +#include "Magnum/configure.h" - /** - * @brief Set fill color - * @return Reference to self (for method chaining) - * - * Default is @cpp 0xffffffff_rgbaf @ce. - * @see @ref setBackgroundColor() - */ - Vector& setColor(const Color4& color); +#ifdef MAGNUM_BUILD_DEPRECATED +#include - #ifndef DOXYGEN_GENERATING_OUTPUT - /* Overloads to remove WTF-factor from method chaining order */ - Vector& bindVectorTexture(GL::Texture2D& texture) { - AbstractVector::bindVectorTexture(texture); - return *this; - } - #endif +#include "Magnum/Shaders/VectorGL.h" - private: - /* Prevent accidentally calling irrelevant functions */ - #ifndef MAGNUM_TARGET_GLES - using GL::AbstractShaderProgram::drawTransformFeedback; - #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - using GL::AbstractShaderProgram::dispatchCompute; - #endif +CORRADE_DEPRECATED_FILE("use Magnum/Shaders/VectorGL.h, the VectorGL class and related typedefs instead") - Flags _flags; - Int _transformationProjectionMatrixUniform{0}, - _textureMatrixUniform{1}, - _backgroundColorUniform{2}, - _colorUniform{3}; -}; +namespace Magnum { namespace Shaders { -/** @brief Two-dimensional vector shader */ -typedef Vector<2> Vector2D; +/** @brief @copybrief Shaders::VectorGL + * @m_deprecated_since_latest Use @ref Shaders::VectorGL "VectorGL" instead. + */ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using Vector CORRADE_DEPRECATED_ALIAS("use VectorGL instead") = VectorGL; +#endif -/** @brief Three-dimensional vector shader */ -typedef Vector<3> Vector3D; +/** @brief @copybrief VectorGL2D + * @m_deprecated_since_latest Use @ref VectorGL2D instead. + */ +typedef CORRADE_DEPRECATED("use VectorGL2D instead") VectorGL2D Vector2D; -#ifdef DOXYGEN_GENERATING_OUTPUT -/** @debugoperatorclassenum{Vector,Vector::Flag} */ -template Debug& operator<<(Debug& debug, Vector::Flag value); +/** @brief @copybrief VectorGL3D + * @m_deprecated_since_latest Use @ref VectorGL3D instead. + */ +typedef CORRADE_DEPRECATED("use VectorGL3D instead") VectorGL3D Vector3D; -/** @debugoperatorclassenum{Vector,Vector::Flags} */ -template Debug& operator<<(Debug& debug, Vector::Flags value); +}} #else -namespace Implementation { - MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, VectorFlag value); - MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, VectorFlags value); - CORRADE_ENUMSET_OPERATORS(VectorFlags) -} +#error use Magnum/Shaders/VectorGL.h, the VectorGL class and related typedefs instead #endif -}} - #endif diff --git a/src/Magnum/Shaders/Vector.cpp b/src/Magnum/Shaders/VectorGL.cpp similarity index 78% rename from src/Magnum/Shaders/Vector.cpp rename to src/Magnum/Shaders/VectorGL.cpp index c61655d69..6e3a3fb68 100644 --- a/src/Magnum/Shaders/Vector.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "Vector.h" +#include "VectorGL.h" #include #include @@ -40,13 +40,13 @@ namespace Magnum { namespace Shaders { -template Vector::Vector(const Flags flags): _flags{flags} { +template VectorGL::VectorGL(const Flags flags): _flags{flags} { #ifdef MAGNUM_BUILD_STATIC /* Import resources on static build, if not already */ - if(!Utility::Resource::hasGroup("MagnumShaders")) + if(!Utility::Resource::hasGroup("MagnumShadersGL")) importShaderResources(); #endif - Utility::Resource rs("MagnumShaders"); + Utility::Resource rs("MagnumShadersGL"); #ifndef MAGNUM_TARGET_GLES const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); @@ -74,8 +74,8 @@ template Vector::Vector(const Flags flags): if(!GL::Context::current().isExtensionSupported(version)) #endif { - GL::AbstractShaderProgram::bindAttributeLocation(AbstractVector::Position::Location, "position"); - GL::AbstractShaderProgram::bindAttributeLocation(AbstractVector::TextureCoordinates::Location, "textureCoordinates"); + GL::AbstractShaderProgram::bindAttributeLocation(AbstractVectorGL::Position::Location, "position"); + GL::AbstractShaderProgram::bindAttributeLocation(AbstractVectorGL::TextureCoordinates::Location, "textureCoordinates"); } #endif @@ -96,7 +96,7 @@ template Vector::Vector(const Flags flags): if(!GL::Context::current().isExtensionSupported(version)) #endif { - GL::AbstractShaderProgram::setUniform(GL::AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractVector::VectorTextureUnit); + GL::AbstractShaderProgram::setUniform(GL::AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractVectorGL::VectorTextureUnit); } /* Set defaults in OpenGL ES (for desktop they are set in shader code itself) */ @@ -108,39 +108,39 @@ template Vector::Vector(const Flags flags): #endif } -template Vector& Vector::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { +template VectorGL& VectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { GL::AbstractShaderProgram::setUniform(_transformationProjectionMatrixUniform, matrix); return *this; } -template Vector& Vector::setTextureMatrix(const Matrix3& matrix) { +template VectorGL& VectorGL::setTextureMatrix(const Matrix3& matrix) { CORRADE_ASSERT(_flags & Flag::TextureTransformation, - "Shaders::Vector::setTextureMatrix(): the shader was not created with texture transformation enabled", *this); + "Shaders::VectorGL::setTextureMatrix(): the shader was not created with texture transformation enabled", *this); GL::AbstractShaderProgram::setUniform(_textureMatrixUniform, matrix); return *this; } -template Vector& Vector::setBackgroundColor(const Color4& color) { +template VectorGL& VectorGL::setBackgroundColor(const Color4& color) { GL::AbstractShaderProgram::setUniform(_backgroundColorUniform, color); return *this; } -template Vector& Vector::setColor(const Color4& color) { +template VectorGL& VectorGL::setColor(const Color4& color) { GL::AbstractShaderProgram::setUniform(_colorUniform, color); return *this; } -template class Vector<2>; -template class Vector<3>; +template class VectorGL<2>; +template class VectorGL<3>; namespace Implementation { -Debug& operator<<(Debug& debug, const VectorFlag value) { - debug << "Shaders::Vector::Flag" << Debug::nospace; +Debug& operator<<(Debug& debug, const VectorGLFlag value) { + debug << "Shaders::VectorGL::Flag" << Debug::nospace; switch(value) { /* LCOV_EXCL_START */ - #define _c(v) case VectorFlag::v: return debug << "::" #v; + #define _c(v) case VectorGLFlag::v: return debug << "::" #v; _c(TextureTransformation) #undef _c /* LCOV_EXCL_STOP */ @@ -149,9 +149,9 @@ Debug& operator<<(Debug& debug, const VectorFlag value) { return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedByte(value)) << Debug::nospace << ")"; } -Debug& operator<<(Debug& debug, const VectorFlags value) { - return Containers::enumSetDebugOutput(debug, value, "Shaders::Vector::Flags{}", { - VectorFlag::TextureTransformation +Debug& operator<<(Debug& debug, const VectorGLFlags value) { + return Containers::enumSetDebugOutput(debug, value, "Shaders::VectorGL::Flags{}", { + VectorGLFlag::TextureTransformation }); } diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h new file mode 100644 index 000000000..8cca43e87 --- /dev/null +++ b/src/Magnum/Shaders/VectorGL.h @@ -0,0 +1,242 @@ +#ifndef Magnum_Shaders_VectorGL_h +#define Magnum_Shaders_VectorGL_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Shaders::VectorGL, typedef @ref Magnum::Shaders::VectorGL2D, @ref Magnum::Shaders::VectorGL3D + * @m_since_latest + */ + +#include "Magnum/DimensionTraits.h" +#include "Magnum/Shaders/AbstractVectorGL.h" +#include "Magnum/Shaders/visibility.h" + +namespace Magnum { namespace Shaders { + +namespace Implementation { + enum class VectorGLFlag: UnsignedByte { + TextureTransformation = 1 << 0 + }; + typedef Containers::EnumSet VectorGLFlags; +} + +/** +@brief Vector OpenGL shader +@m_since_latest + +Renders vector art in plain grayscale form. See also @ref DistanceFieldVectorGL +for more advanced effects. For rendering an unchanged texture you can use the +@ref FlatGL shader. You need to provide the @ref Position and +@ref TextureCoordinates attributes in your triangle mesh and call at least +@ref bindVectorTexture(). By default, the shader renders the texture with a +white color in an identity transformation. Use +@ref setTransformationProjectionMatrix(), @ref setColor() and others to +configure the shader. + +@image html shaders-vector.png width=256px + +Alpha / transparency is supported by the shader implicitly, but to have it +working on the framebuffer, you need to enable +@ref GL::Renderer::Feature::Blending and set up the blending function. See +@ref GL::Renderer::setBlendFunction() for details. + +@section Shaders-VectorGL-usage Example usage + +Common mesh setup: + +@snippet MagnumShaders-gl.cpp VectorGL-usage1 + +Common rendering setup: + +@snippet MagnumShaders-gl.cpp VectorGL-usage2 + +@see @ref shaders, @ref VectorGL2D, @ref VectorGL3D +*/ +template class MAGNUM_SHADERS_EXPORT VectorGL: public AbstractVectorGL { + public: + #ifdef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Flag + * @m_since{2020,06} + * + * @see @ref Flags, @ref flags() + */ + enum class Flag: UnsignedByte { + /** + * Enable texture coordinate transformation. + * @see @ref setTextureMatrix() + * @m_since{2020,06} + */ + TextureTransformation = 1 << 0 + }; + + /** + * @brief Flags + * @m_since{2020,06} + * + * @see @ref flags() + */ + typedef Containers::EnumSet Flags; + #else + /* Done this way to be prepared for possible future diversion of 2D + and 3D flags (e.g. introducing 3D-specific features) */ + typedef Implementation::VectorGLFlag Flag; + typedef Implementation::VectorGLFlags Flags; + #endif + + /** + * @brief Constructor + * @param flags Flags + */ + explicit VectorGL(Flags flags = {}); + + /** + * @brief Construct without creating the underlying OpenGL object + * + * The constructed instance is equivalent to a moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit VectorGL(NoCreateT) noexcept + /** @todoc remove workaround when doxygen is sane */ + #ifndef DOXYGEN_GENERATING_OUTPUT + : AbstractVectorGL{NoCreate} + #endif + {} + + /** @brief Copying is not allowed */ + VectorGL(const VectorGL&) = delete; + + /** @brief Move constructor */ + VectorGL(VectorGL&&) noexcept = default; + + /** @brief Copying is not allowed */ + VectorGL& operator=(const VectorGL&) = delete; + + /** @brief Move assignment */ + VectorGL& operator=(VectorGL&&) noexcept = default; + + /** + * @brief Flags + * @m_since{2020,06} + */ + Flags flags() const { return _flags; } + + /** + * @brief Set transformation and projection matrix + * @return Reference to self (for method chaining) + * + * Default is an identity matrix. + */ + VectorGL& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); + + /** + * @brief Set texture coordinate transformation matrix + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * Expects that the shader was created with + * @ref Flag::TextureTransformation enabled. Initial value is an + * identity matrix. + */ + VectorGL& setTextureMatrix(const Matrix3& matrix); + + /** + * @brief Set background color + * @return Reference to self (for method chaining) + * + * Default is @cpp 0x00000000_rgbaf @ce. + * @see @ref setColor() + */ + VectorGL& setBackgroundColor(const Color4& color); + + /** + * @brief Set fill color + * @return Reference to self (for method chaining) + * + * Default is @cpp 0xffffffff_rgbaf @ce. + * @see @ref setBackgroundColor() + */ + VectorGL& setColor(const Color4& color); + + #ifndef DOXYGEN_GENERATING_OUTPUT + /* Overloads to remove WTF-factor from method chaining order */ + VectorGL& bindVectorTexture(GL::Texture2D& texture) { + AbstractVectorGL::bindVectorTexture(texture); + return *this; + } + #endif + + private: + /* Prevent accidentally calling irrelevant functions */ + #ifndef MAGNUM_TARGET_GLES + using GL::AbstractShaderProgram::drawTransformFeedback; + #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + using GL::AbstractShaderProgram::dispatchCompute; + #endif + + Flags _flags; + Int _transformationProjectionMatrixUniform{0}, + _textureMatrixUniform{1}, + _backgroundColorUniform{2}, + _colorUniform{3}; +}; + +/** +@brief Two-dimensional vector OpenGL shader +@m_since_latest +*/ +typedef VectorGL<2> VectorGL2D; + +/** +@brief Three-dimensional vector OpenGL shader +@m_since_latest +*/ +typedef VectorGL<3> VectorGL3D; + +#ifdef DOXYGEN_GENERATING_OUTPUT +/** @debugoperatorclassenum{VectorGL,VectorGL::Flag} */ +template Debug& operator<<(Debug& debug, VectorGL::Flag value); + +/** @debugoperatorclassenum{VectorGL,VectorGL::Flags} */ +template Debug& operator<<(Debug& debug, VectorGL::Flags value); +#else +namespace Implementation { + MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, VectorGLFlag value); + MAGNUM_SHADERS_EXPORT Debug& operator<<(Debug& debug, VectorGLFlags value); + CORRADE_ENUMSET_OPERATORS(VectorGLFlags) +} +#endif + +}} + +#endif diff --git a/src/Magnum/Shaders/VertexColor.h b/src/Magnum/Shaders/VertexColor.h index ccf70e07a..dc8992428 100644 --- a/src/Magnum/Shaders/VertexColor.h +++ b/src/Magnum/Shaders/VertexColor.h @@ -25,140 +25,46 @@ DEALINGS IN THE SOFTWARE. */ +#ifdef MAGNUM_BUILD_DEPRECATED /** @file - * @brief Class @ref Magnum::Shaders::VertexColor + * @brief Typedef @ref Magnum::Shaders::VertexColor, alias @ref Magnum::Shaders::VertexColor2D, @ref Magnum::Shaders::VertexColor3D + * @m_deprecated_since_latest Use @ref Magnum/Shaders/VertexColorGL.h, the + * @ref Magnum::Shaders::VertexColorGL "VertexColorGL" class and + * related typedefs instead. */ +#endif -#include "Magnum/DimensionTraits.h" -#include "Magnum/GL/AbstractShaderProgram.h" -#include "Magnum/Shaders/Generic.h" -#include "Magnum/Shaders/visibility.h" - -namespace Magnum { namespace Shaders { - -/** -@brief Vertex color shader - -Draws a vertex-colored mesh. You need to provide @ref Position and @ref Color3 -/ @ref Color4 attributes in your triangle mesh. By default, the shader renders -the mesh in an identity transformation. Use -@ref setTransformationProjectionMatrix() to configure the shader. - -@image html shaders-vertexcolor.png width=256px - -This shader is equivalent to @ref Flat with @ref Flat::Flag::VertexColor -enabled; the 3D version of this shader is equivalent to @ref Phong with -@ref Phong::Flag::VertexColor enabled. In both cases this implementation is -much simpler and thus likely also faster. - -Alpha / transparency is supported by the shader implicitly, but to have it -working on the framebuffer, you need to enable -@ref GL::Renderer::Feature::Blending and set up the blending function. See -@ref GL::Renderer::setBlendFunction() for details. - -@section Shaders-VertexColor-example Example usage - -Common mesh setup. The shader accepts either three- or four-component color -attribute, use either @ref Color3 or @ref Color4 to specify which one you use. - -@snippet MagnumShaders.cpp VertexColor-usage1 - -Common rendering setup: - -@snippet MagnumShaders.cpp VertexColor-usage2 - -@see @ref shaders, @ref VertexColor2D, @ref VertexColor3D -*/ -template class MAGNUM_SHADERS_EXPORT VertexColor: public GL::AbstractShaderProgram { - public: - /** - * @brief Vertex position - * - * @ref shaders-generic "Generic attribute", - * @ref Magnum::Vector2 "Vector2" in 2D @ref Magnum::Vector3 "Vector3" - * in 3D. - */ - typedef typename Generic::Position Position; - - /** - * @brief Three-component vertex color - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Color3. Use - * either this or the @ref Color4 attribute. - */ - typedef typename Generic::Color3 Color3; - - /** - * @brief Four-component vertex color - * - * @ref shaders-generic "Generic attribute", @ref Magnum::Color4. Use - * either this or the @ref Color3 attribute. - */ - typedef typename Generic::Color4 Color4; - - enum: UnsignedInt { - /** - * Color shader output. @ref shaders-generic "Generic output", - * present always. Expects three- or four-component floating-point - * or normalized buffer attachment. - */ - ColorOutput = Generic::ColorOutput - }; - - explicit VertexColor(); - - /** - * @brief Construct without creating the underlying OpenGL object - * - * The constructed instance is equivalent to a moved-from state. Useful - * in cases where you will overwrite the instance later anyway. Move - * another object over it to make it useful. - * - * This function can be safely used for constructing (and later - * destructing) objects even without any OpenGL context being active. - * However note that this is a low-level and a potentially dangerous - * API, see the documentation of @ref NoCreate for alternatives. - */ - explicit VertexColor(NoCreateT) noexcept: AbstractShaderProgram{NoCreate} {} - - /** @brief Copying is not allowed */ - VertexColor(const VertexColor&) = delete; - - /** @brief Move constructor */ - VertexColor(VertexColor&&) noexcept = default; +#include "Magnum/configure.h" - /** @brief Copying is not allowed */ - VertexColor& operator=(const VertexColor&) = delete; +#ifdef MAGNUM_BUILD_DEPRECATED +#include - /** @brief Move assignment */ - VertexColor& operator=(VertexColor&&) noexcept = default; +#include "Magnum/Shaders/VertexColorGL.h" - /** - * @brief Set transformation and projection matrix - * @return Reference to self (for method chaining) - * - * Default is an identity matrix. - */ - VertexColor& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); +CORRADE_DEPRECATED_FILE("use Magnum/Shaders/VertexColorGL.h, the VertexColorGL class and related typedefs instead") - private: - /* Prevent accidentally calling irrelevant functions */ - #ifndef MAGNUM_TARGET_GLES - using GL::AbstractShaderProgram::drawTransformFeedback; - #endif - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - using GL::AbstractShaderProgram::dispatchCompute; - #endif +namespace Magnum { namespace Shaders { - Int _transformationProjectionMatrixUniform{0}; -}; +/** @brief @copybrief VertexColorGL + * @m_deprecated_since_latest Use @ref VertexColorGL instead. + */ +#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Multiple definitions still broken */ +template using VertexColor CORRADE_DEPRECATED_ALIAS("use VertexColorGL instead") = VertexColorGL; +#endif -/** @brief 2D vertex color shader */ -typedef VertexColor<2> VertexColor2D; +/** @brief @copybrief VertexColorGL2D + * @m_deprecated_since_latest Use @ref VertexColorGL2D instead. + */ +typedef CORRADE_DEPRECATED("use VertexColorGL2D instead") VertexColorGL2D VertexColor2D; -/** @brief 3D vertex color shader */ -typedef VertexColor<3> VertexColor3D; +/** @brief @copybrief VertexColorGL3D + * @m_deprecated_since_latest Use @ref VertexColorGL3D instead. + */ +typedef CORRADE_DEPRECATED("use VertexColorGL3D instead") VertexColorGL3D VertexColor3D; }} +#else +#error use Magnum/Shaders/VertexColorGL.h, the VertexColorGL class and related typedefs instead +#endif #endif diff --git a/src/Magnum/Shaders/VertexColor.cpp b/src/Magnum/Shaders/VertexColorGL.cpp similarity index 89% rename from src/Magnum/Shaders/VertexColor.cpp rename to src/Magnum/Shaders/VertexColorGL.cpp index 36510ff50..a767d74b4 100644 --- a/src/Magnum/Shaders/VertexColor.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "VertexColor.h" +#include "VertexColorGL.h" #include #include @@ -39,13 +39,13 @@ namespace Magnum { namespace Shaders { -template VertexColor::VertexColor() { +template VertexColorGL::VertexColorGL() { #ifdef MAGNUM_BUILD_STATIC /* Import resources on static build, if not already */ - if(!Utility::Resource::hasGroup("MagnumShaders")) + if(!Utility::Resource::hasGroup("MagnumShadersGL")) importShaderResources(); #endif - Utility::Resource rs("MagnumShaders"); + Utility::Resource rs("MagnumShadersGL"); #ifndef MAGNUM_TARGET_GLES const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); @@ -92,12 +92,12 @@ template VertexColor::VertexColor() { #endif } -template VertexColor& VertexColor::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { +template VertexColorGL& VertexColorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { setUniform(_transformationProjectionMatrixUniform, matrix); return *this; } -template class VertexColor<2>; -template class VertexColor<3>; +template class VertexColorGL<2>; +template class VertexColorGL<3>; }} diff --git a/src/Magnum/Shaders/VertexColorGL.h b/src/Magnum/Shaders/VertexColorGL.h new file mode 100644 index 000000000..5bbd17fdc --- /dev/null +++ b/src/Magnum/Shaders/VertexColorGL.h @@ -0,0 +1,172 @@ +#ifndef Magnum_Shaders_VertexColorGL_h +#define Magnum_Shaders_VertexColorGL_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021 Vladimír Vondruš + + 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::Shaders::VertexColorGL + * @m_since_latest + */ + +#include "Magnum/DimensionTraits.h" +#include "Magnum/GL/AbstractShaderProgram.h" +#include "Magnum/Shaders/GenericGL.h" +#include "Magnum/Shaders/visibility.h" + +namespace Magnum { namespace Shaders { + +/** +@brief Vertex color OpenGL shader +@m_since_latest + +Draws a vertex-colored mesh. You need to provide @ref Position and @ref Color3 +/ @ref Color4 attributes in your triangle mesh. By default, the shader renders +the mesh in an identity transformation. Use +@ref setTransformationProjectionMatrix() to configure the shader. + +@image html shaders-vertexcolor.png width=256px + +This shader is equivalent to @ref FlatGL with @ref FlatGL::Flag::VertexColor +enabled; the 3D version of this shader is equivalent to @ref PhongGL with +@ref PhongGL::Flag::VertexColor enabled. In both cases this implementation is +much simpler and thus likely also faster. + +Alpha / transparency is supported by the shader implicitly, but to have it +working on the framebuffer, you need to enable +@ref GL::Renderer::Feature::Blending and set up the blending function. See +@ref GL::Renderer::setBlendFunction() for details. + +@section Shaders-VertexColorGL-example Example usage + +Common mesh setup. The shader accepts either three- or four-component color +attribute, use either @ref Color3 or @ref Color4 to specify which one you use. + +@snippet MagnumShaders-gl.cpp VertexColorGL-usage1 + +Common rendering setup: + +@snippet MagnumShaders-gl.cpp VertexColorGL-usage2 + +@see @ref shaders, @ref VertexColorGL2D, @ref VertexColorGL3D +*/ +template class MAGNUM_SHADERS_EXPORT VertexColorGL: public GL::AbstractShaderProgram { + public: + /** + * @brief Vertex position + * + * @ref shaders-generic "Generic attribute", + * @ref Magnum::Vector2 "Vector2" in 2D @ref Magnum::Vector3 "Vector3" + * in 3D. + */ + typedef typename GenericGL::Position Position; + + /** + * @brief Three-component vertex color + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color3. Use + * either this or the @ref Color4 attribute. + */ + typedef typename GenericGL::Color3 Color3; + + /** + * @brief Four-component vertex color + * + * @ref shaders-generic "Generic attribute", @ref Magnum::Color4. Use + * either this or the @ref Color3 attribute. + */ + typedef typename GenericGL::Color4 Color4; + + enum: UnsignedInt { + /** + * Color shader output. @ref shaders-generic "Generic output", + * present always. Expects three- or four-component floating-point + * or normalized buffer attachment. + */ + ColorOutput = GenericGL::ColorOutput + }; + + explicit VertexColorGL(); + + /** + * @brief Construct without creating the underlying OpenGL object + * + * The constructed instance is equivalent to a moved-from state. Useful + * in cases where you will overwrite the instance later anyway. Move + * another object over it to make it useful. + * + * This function can be safely used for constructing (and later + * destructing) objects even without any OpenGL context being active. + * However note that this is a low-level and a potentially dangerous + * API, see the documentation of @ref NoCreate for alternatives. + */ + explicit VertexColorGL(NoCreateT) noexcept: AbstractShaderProgram{NoCreate} {} + + /** @brief Copying is not allowed */ + VertexColorGL(const VertexColorGL&) = delete; + + /** @brief Move constructor */ + VertexColorGL(VertexColorGL&&) noexcept = default; + + /** @brief Copying is not allowed */ + VertexColorGL& operator=(const VertexColorGL&) = delete; + + /** @brief Move assignment */ + VertexColorGL& operator=(VertexColorGL&&) noexcept = default; + + /** + * @brief Set transformation and projection matrix + * @return Reference to self (for method chaining) + * + * Default is an identity matrix. + */ + VertexColorGL& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); + + private: + /* Prevent accidentally calling irrelevant functions */ + #ifndef MAGNUM_TARGET_GLES + using GL::AbstractShaderProgram::drawTransformFeedback; + #endif + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + using GL::AbstractShaderProgram::dispatchCompute; + #endif + + Int _transformationProjectionMatrixUniform{0}; +}; + +/** +@brief 2D vertex color OpenGL shader +@m_since_latest +*/ +typedef VertexColorGL<2> VertexColorGL2D; + +/** +@brief 3D vertex color OpenGL shader +@m_since_latest +*/ +typedef VertexColorGL<3> VertexColorGL3D; + +}} + +#endif diff --git a/src/Magnum/Shaders/resources.conf b/src/Magnum/Shaders/resources-gl.conf similarity index 95% rename from src/Magnum/Shaders/resources.conf rename to src/Magnum/Shaders/resources-gl.conf index 59924c314..f545425c9 100644 --- a/src/Magnum/Shaders/resources.conf +++ b/src/Magnum/Shaders/resources-gl.conf @@ -1,4 +1,4 @@ -group=MagnumShaders +group=MagnumShadersGL [file] filename=AbstractVector.vert diff --git a/src/Magnum/Text/Renderer.cpp b/src/Magnum/Text/Renderer.cpp index a3a5071b3..088561041 100644 --- a/src/Magnum/Text/Renderer.cpp +++ b/src/Magnum/Text/Renderer.cpp @@ -33,7 +33,7 @@ #include "Magnum/GL/Extensions.h" #include "Magnum/GL/Mesh.h" #include "Magnum/Math/Functions.h" -#include "Magnum/Shaders/AbstractVector.h" +#include "Magnum/Shaders/AbstractVectorGL.h" #include "Magnum/Text/AbstractFont.h" #include "Magnum/Text/GlyphCache.h" @@ -255,9 +255,9 @@ template std::tuple Renderer(r); mesh.addVertexBuffer(vertexBuffer, 0, - typename Shaders::AbstractVector::Position( - Shaders::AbstractVector::Position::Components::Two), - typename Shaders::AbstractVector::TextureCoordinates()); + typename Shaders::AbstractVectorGL::Position( + Shaders::AbstractVectorGL::Position::Components::Two), + typename Shaders::AbstractVectorGL::TextureCoordinates()); return r; } @@ -320,8 +320,8 @@ AbstractRenderer::~AbstractRenderer() = default; template Renderer::Renderer(AbstractFont& font, const GlyphCache& cache, const Float size, const Alignment alignment): AbstractRenderer(font, cache, size, alignment) { /* Finalize mesh configuration */ _mesh.addVertexBuffer(_vertexBuffer, 0, - typename Shaders::AbstractVector::Position(Shaders::AbstractVector::Position::Components::Two), - typename Shaders::AbstractVector::TextureCoordinates()); + typename Shaders::AbstractVectorGL::Position(Shaders::AbstractVectorGL::Position::Components::Two), + typename Shaders::AbstractVectorGL::TextureCoordinates()); } void AbstractRenderer::reserve(const uint32_t glyphCount, const GL::BufferUsage vertexBufferUsage, const GL::BufferUsage indexBufferUsage) { diff --git a/src/Magnum/Text/Renderer.h b/src/Magnum/Text/Renderer.h index 5acc03b01..eb9edfdf9 100644 --- a/src/Magnum/Text/Renderer.h +++ b/src/Magnum/Text/Renderer.h @@ -202,7 +202,7 @@ asynchronous buffer updates. There is no similar extension in WebGL, thus plain (and slow) buffer updates are used there. @see @ref Renderer2D, @ref Renderer3D, @ref AbstractFont, - @ref Shaders::AbstractVector + @ref Shaders::AbstractVectorGL */ template class MAGNUM_TEXT_EXPORT Renderer: public AbstractRenderer { public: @@ -217,7 +217,7 @@ template class MAGNUM_TEXT_EXPORT Renderer: public Abstr * @param usage Usage of vertex and index buffer * @param alignment Text alignment * - * Returns mesh prepared for use with @ref Shaders::AbstractVector + * Returns mesh prepared for use with @ref Shaders::AbstractVectorGL * subclasses and rectangle spanning the rendered text. */ static std::tuple render(AbstractFont& font, const GlyphCache& cache, Float size, const std::string& text, GL::Buffer& vertexBuffer, GL::Buffer& indexBuffer, GL::BufferUsage usage, Alignment alignment = Alignment::LineLeft); diff --git a/src/Magnum/TextureTools/DistanceField.h b/src/Magnum/TextureTools/DistanceField.h index 9195d5209..8d560dffe 100644 --- a/src/Magnum/TextureTools/DistanceField.h +++ b/src/Magnum/TextureTools/DistanceField.h @@ -72,7 +72,7 @@ The resulting texture can be used with bilinear filtering. It can be converted back to binary form in shader using e.g. GLSL @glsl smoothstep() @ce function with step around 0.5 to create antialiased edges. Or you can exploit the distance field features to create many other effects. See also -@ref Shaders::DistanceFieldVector. +@ref Shaders::DistanceFieldVectorGL. Based on: *Chris Green - Improved Alpha-Tested Magnification for Vector Textures and Special Effects, SIGGRAPH 2007, diff --git a/src/Magnum/TextureTools/distancefieldconverter.cpp b/src/Magnum/TextureTools/distancefieldconverter.cpp index aa230cc30..cc072cf57 100644 --- a/src/Magnum/TextureTools/distancefieldconverter.cpp +++ b/src/Magnum/TextureTools/distancefieldconverter.cpp @@ -113,7 +113,7 @@ Arguments: Images with @ref PixelFormat::R8Unorm, @ref PixelFormat::RGB8Unorm or @ref PixelFormat::RGBA8Unorm are accepted on input. -The resulting image can be then used with @ref Shaders::DistanceFieldVector +The resulting image can be then used with @ref Shaders::DistanceFieldVectorGL shader. See also @ref TextureTools::DistanceField for more information about the algorithm and parameters. diff --git a/src/Magnum/Trade/MeshData.h b/src/Magnum/Trade/MeshData.h index 613ae00e7..a83083fb9 100644 --- a/src/Magnum/Trade/MeshData.h +++ b/src/Magnum/Trade/MeshData.h @@ -66,7 +66,7 @@ enum class MeshAttribute: UnsignedShort { * @ref VertexFormat::Vector3b, @ref VertexFormat::Vector3bNormalized, * @ref VertexFormat::Vector3us, @ref VertexFormat::Vector3usNormalized, * @ref VertexFormat::Vector3s or @ref VertexFormat::Vector3sNormalized. - * Corresponds to @ref Shaders::Generic::Position. + * Corresponds to @ref Shaders::GenericGL::Position. * @see @ref MeshData::positions2DAsArray(), * @ref MeshData::positions3DAsArray() */ @@ -86,8 +86,8 @@ enum class MeshAttribute: UnsignedShort { * * @snippet MagnumTrade.cpp MeshAttribute-bitangent-from-tangent * - * Corresponds to @ref Shaders::Generic::Tangent or - * @ref Shaders::Generic::Tangent4. + * Corresponds to @ref Shaders::GenericGL::Tangent or + * @ref Shaders::GenericGL::Tangent4. * @see @ref MeshData::tangentsAsArray(), * @ref MeshData::bitangentSignsAsArray() */ @@ -99,7 +99,7 @@ enum class MeshAttribute: UnsignedShort { * @ref VertexFormat::Vector3sNormalized. For better storage efficiency, * the bitangent can be also reconstructed from the normal and tangent, see * @ref MeshAttribute::Tangent for more information. Corresponds to - * @ref Shaders::Generic::Bitangent. + * @ref Shaders::GenericGL::Bitangent. * @see @ref MeshData::bitangentsAsArray() */ Bitangent, @@ -108,7 +108,7 @@ enum class MeshAttribute: UnsignedShort { * Normal. Type is usually @ref VertexFormat::Vector3, but can be also * @ref VertexFormat::Vector3h. @ref VertexFormat::Vector3bNormalized or * @ref VertexFormat::Vector3sNormalized. Corresponds to - * @ref Shaders::Generic::Normal. + * @ref Shaders::GenericGL::Normal. * @see @ref MeshData::normalsAsArray() */ Normal, @@ -120,7 +120,7 @@ enum class MeshAttribute: UnsignedShort { * @ref VertexFormat::Vector2b, @ref VertexFormat::Vector2bNormalized, * @ref VertexFormat::Vector2us, @ref VertexFormat::Vector2usNormalized, * @ref VertexFormat::Vector2s or @ref VertexFormat::Vector2sNormalized. - * Corresponds to @ref Shaders::Generic::TextureCoordinates. + * Corresponds to @ref Shaders::GenericGL::TextureCoordinates. * @see @ref MeshData::textureCoordinates2DAsArray() */ TextureCoordinates, @@ -133,7 +133,7 @@ enum class MeshAttribute: UnsignedShort { * @ref VertexFormat::Vector3usNormalized, * @ref VertexFormat::Vector4ubNormalized or * @ref VertexFormat::Vector4usNormalized. Corresponds to - * @ref Shaders::Generic::Color3 or @ref Shaders::Generic::Color4. + * @ref Shaders::GenericGL::Color3 or @ref Shaders::GenericGL::Color4. * @see @ref MeshData::colorsAsArray() */ Color, @@ -142,7 +142,7 @@ enum class MeshAttribute: UnsignedShort { * (Instanced) object ID for editor selection or scene annotation. Type is * usually @ref VertexFormat::UnsignedInt, but can be also * @ref VertexFormat::UnsignedShort or @ref VertexFormat::UnsignedByte. - * Corresponds to @ref Shaders::Generic::ObjectId. + * Corresponds to @ref Shaders::GenericGL::ObjectId. * @see @ref MeshData::objectIdsAsArray() */ ObjectId, From e26f90957cccd5dfbd3b0052a9eca14d7f5736a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 16 Apr 2021 17:20:54 +0200 Subject: [PATCH 144/161] Shaders: wait, how did the linker work for the whole decade?! No issue on GCC, only Clang and MSVC started failing once I renamed the shaders. These four are the only that don't have the export macro attached AND YET it somehow worked without any problem until now. --- src/Magnum/Shaders/DistanceFieldVectorGL.cpp | 4 ++-- src/Magnum/Shaders/FlatGL.cpp | 4 ++-- src/Magnum/Shaders/VectorGL.cpp | 4 ++-- src/Magnum/Shaders/VertexColorGL.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp index 19c50301f..32c8e8795 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -145,8 +145,8 @@ template DistanceFieldVectorGL& DistanceFiel return *this; } -template class DistanceFieldVectorGL<2>; -template class DistanceFieldVectorGL<3>; +template class MAGNUM_SHADERS_EXPORT DistanceFieldVectorGL<2>; +template class MAGNUM_SHADERS_EXPORT DistanceFieldVectorGL<3>; namespace Implementation { diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 3d9b1c79e..2501bf049 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -191,8 +191,8 @@ template FlatGL& FlatGL::setObje } #endif -template class FlatGL<2>; -template class FlatGL<3>; +template class MAGNUM_SHADERS_EXPORT FlatGL<2>; +template class MAGNUM_SHADERS_EXPORT FlatGL<3>; namespace Implementation { diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index 6e3a3fb68..d29cf4a1f 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -130,8 +130,8 @@ template VectorGL& VectorGL::set return *this; } -template class VectorGL<2>; -template class VectorGL<3>; +template class MAGNUM_SHADERS_EXPORT VectorGL<2>; +template class MAGNUM_SHADERS_EXPORT VectorGL<3>; namespace Implementation { diff --git a/src/Magnum/Shaders/VertexColorGL.cpp b/src/Magnum/Shaders/VertexColorGL.cpp index a767d74b4..311ae603d 100644 --- a/src/Magnum/Shaders/VertexColorGL.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -97,7 +97,7 @@ template VertexColorGL& VertexColorGL; -template class VertexColorGL<3>; +template class MAGNUM_SHADERS_EXPORT VertexColorGL<2>; +template class MAGNUM_SHADERS_EXPORT VertexColorGL<3>; }} From f70bbef4738fe6e34f75c802568316174dd831bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 17 Apr 2021 18:56:03 +0200 Subject: [PATCH 145/161] Shaders: group uniform setters and texture binding functions together. Otherwise it would get way too messy with the introduction of uniform buffers. --- src/Magnum/Shaders/AbstractVectorGL.h | 8 ++ src/Magnum/Shaders/DistanceFieldVectorGL.h | 8 ++ src/Magnum/Shaders/FlatGL.cpp | 14 +- src/Magnum/Shaders/FlatGL.h | 38 ++++-- src/Magnum/Shaders/MeshVisualizerGL.h | 88 ++++++++---- src/Magnum/Shaders/PhongGL.cpp | 70 +++++----- src/Magnum/Shaders/PhongGL.h | 148 ++++++++++++--------- src/Magnum/Shaders/VectorGL.h | 8 ++ src/Magnum/Shaders/VertexColorGL.h | 8 ++ 9 files changed, 245 insertions(+), 145 deletions(-) diff --git a/src/Magnum/Shaders/AbstractVectorGL.h b/src/Magnum/Shaders/AbstractVectorGL.h index c6b8a0c01..95933640d 100644 --- a/src/Magnum/Shaders/AbstractVectorGL.h +++ b/src/Magnum/Shaders/AbstractVectorGL.h @@ -82,6 +82,10 @@ template class AbstractVectorGL: public GL::AbstractShad /** @brief Move assignment */ AbstractVectorGL& operator=(AbstractVectorGL&&) noexcept = default; + /** @{ + * @name Texture binding + */ + /** * @brief Bind vector texture * @return Reference to self (for method chaining) @@ -93,6 +97,10 @@ template class AbstractVectorGL: public GL::AbstractShad */ AbstractVectorGL& bindVectorTexture(GL::Texture2D& texture); + /** + * @} + */ + #ifndef DOXYGEN_GENERATING_OUTPUT protected: #else diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.h b/src/Magnum/Shaders/DistanceFieldVectorGL.h index 92ede2175..e588179a8 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.h +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.h @@ -154,6 +154,10 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector */ Flags flags() const { return _flags; } + /** @{ + * @name Uniform setters + */ + /** * @brief Set transformation and projection matrix * @return Reference to self (for method chaining) @@ -218,6 +222,10 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector */ DistanceFieldVectorGL& setSmoothness(Float value); + /** + * @} + */ + #ifndef DOXYGEN_GENERATING_OUTPUT /* Overloads to remove WTF-factor from method chaining order */ DistanceFieldVectorGL& bindVectorTexture(GL::Texture2D& texture) { diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 2501bf049..bfd7b355a 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -168,13 +168,6 @@ template FlatGL& FlatGL::setColo return *this; } -template FlatGL& FlatGL::bindTexture(GL::Texture2D& texture) { - CORRADE_ASSERT(_flags & Flag::Textured, - "Shaders::FlatGL::bindTexture(): the shader was not created with texturing enabled", *this); - texture.bind(TextureUnit); - return *this; -} - template FlatGL& FlatGL::setAlphaMask(Float mask) { CORRADE_ASSERT(_flags & Flag::AlphaMask, "Shaders::FlatGL::setAlphaMask(): the shader was not created with alpha mask enabled", *this); @@ -191,6 +184,13 @@ template FlatGL& FlatGL::setObje } #endif +template FlatGL& FlatGL::bindTexture(GL::Texture2D& texture) { + CORRADE_ASSERT(_flags & Flag::Textured, + "Shaders::FlatGL::bindTexture(): the shader was not created with texturing enabled", *this); + texture.bind(TextureUnit); + return *this; +} + template class MAGNUM_SHADERS_EXPORT FlatGL<2>; template class MAGNUM_SHADERS_EXPORT FlatGL<3>; diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 7256bf3cf..8fa33dfb4 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -416,6 +416,10 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: /** @brief Flags */ Flags flags() const { return _flags; } + /** @{ + * @name Uniform setters + */ + /** * @brief Set transformation and projection matrix * @return Reference to self (for method chaining) @@ -446,17 +450,6 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: */ FlatGL& setColor(const Magnum::Color4& color); - /** - * @brief Bind a color texture - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::Textured - * enabled. - * @see @ref setColor(), @ref Flag::TextureTransformation, - * @ref setTextureMatrix() - */ - FlatGL& bindTexture(GL::Texture2D& texture); - /** * @brief Set alpha mask value * @return Reference to self (for method chaining) @@ -489,6 +482,29 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: FlatGL& setObjectId(UnsignedInt id); #endif + /** + * @} + */ + + /** @{ + * @name Texture binding + */ + + /** + * @brief Bind a color texture + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::Textured + * enabled. + * @see @ref setColor(), @ref Flag::TextureTransformation, + * @ref setTextureMatrix() + */ + FlatGL& bindTexture(GL::Texture2D& texture); + + /** + * @} + */ + private: /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h index c0997486e..6929bde97 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.h +++ b/src/Magnum/Shaders/MeshVisualizerGL.h @@ -249,6 +249,10 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua return Flag(UnsignedShort(Implementation::MeshVisualizerGLBase::_flags)); } + /** @{ + * @name Uniform setters + */ + /** * @brief Set transformation and projection matrix * @return Reference to self (for method chaining) @@ -309,11 +313,6 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua MeshVisualizerGL2D& setColorMapTransformation(Float offset, Float scale) { return static_cast(Implementation::MeshVisualizerGLBase::setColorMapTransformation(offset, scale)); } - - /** @copydoc MeshVisualizerGL3D::bindColorMapTexture() */ - MeshVisualizerGL2D& bindColorMapTexture(GL::Texture2D& texture) { - return static_cast(Implementation::MeshVisualizerGLBase::bindColorMapTexture(texture)); - } #endif /** @@ -326,6 +325,25 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua */ MeshVisualizerGL2D& setSmoothness(Float smoothness); + /** + * @} + */ + + /** @{ + * @name Texture binding + */ + + #ifndef MAGNUM_TARGET_GLES2 + /** @copydoc MeshVisualizerGL3D::bindColorMapTexture() */ + MeshVisualizerGL2D& bindColorMapTexture(GL::Texture2D& texture) { + return static_cast(Implementation::MeshVisualizerGLBase::bindColorMapTexture(texture)); + } + #endif + + /** + * @} + */ + private: Int _transformationProjectionMatrixUniform{0}; }; @@ -801,6 +819,10 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua return Flag(UnsignedShort(Implementation::MeshVisualizerGLBase::_flags)); } + /** @{ + * @name Uniform setters + */ + #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Set transformation and projection matrix @@ -933,27 +955,6 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua MeshVisualizerGL3D& setColorMapTransformation(Float offset, Float scale) { return static_cast(Implementation::MeshVisualizerGLBase::setColorMapTransformation(offset, scale)); } - - /** - * @brief Bind a color map texture - * @return Reference to self (for method chaining) - * @m_since{2020,06} - * - * See also @ref setColorMapTransformation(). Expects that either - * @ref Flag::InstancedObjectId or @ref Flag::PrimitiveId / - * @ref Flag::PrimitiveIdFromVertexId is enabled. - * @requires_gles30 Object ID visualization requires integer attributes - * while primitive ID visualization requires the `gl_VertexID` / - * `gl_PrimitiveID` builtins, neither of which is available in - * OpenGL ES 2.0. - * @requires_webgl20 Object ID visualization requires integer - * attributes while primitive ID visualization requires at least - * the `gl_VertexID` builtin, neither of which is available in - * WebGL 1. - */ - MeshVisualizerGL3D& bindColorMapTexture(GL::Texture2D& texture) { - return static_cast(Implementation::MeshVisualizerGLBase::bindColorMapTexture(texture)); - } #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) @@ -1008,6 +1009,41 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua */ MeshVisualizerGL3D& setSmoothness(Float smoothness); + /** + * @} + */ + + /** @{ + * @name Texture binding + */ + + #ifndef MAGNUM_TARGET_GLES2 + /** + * @brief Bind a color map texture + * @return Reference to self (for method chaining) + * @m_since{2020,06} + * + * See also @ref setColorMapTransformation(). Expects that either + * @ref Flag::InstancedObjectId or @ref Flag::PrimitiveId / + * @ref Flag::PrimitiveIdFromVertexId is enabled. + * @requires_gles30 Object ID visualization requires integer attributes + * while primitive ID visualization requires the `gl_VertexID` / + * `gl_PrimitiveID` builtins, neither of which is available in + * OpenGL ES 2.0. + * @requires_webgl20 Object ID visualization requires integer + * attributes while primitive ID visualization requires at least + * the `gl_VertexID` builtin, neither of which is available in + * WebGL 1. + */ + MeshVisualizerGL3D& bindColorMapTexture(GL::Texture2D& texture) { + return static_cast(Implementation::MeshVisualizerGLBase::bindColorMapTexture(texture)); + } + #endif + + /** + * @} + */ + private: Int _transformationMatrixUniform{0}, _projectionMatrixUniform{7}; diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index 4dfa76ae3..de4494706 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -280,51 +280,16 @@ PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) { return *this; } -PhongGL& PhongGL::bindAmbientTexture(GL::Texture2D& texture) { - CORRADE_ASSERT(_flags & Flag::AmbientTexture, - "Shaders::PhongGL::bindAmbientTexture(): the shader was not created with ambient texture enabled", *this); - texture.bind(AmbientTextureUnit); - return *this; -} - PhongGL& PhongGL::setDiffuseColor(const Magnum::Color4& color) { if(_lightCount) setUniform(_diffuseColorUniform, color); return *this; } -PhongGL& PhongGL::bindDiffuseTexture(GL::Texture2D& texture) { - CORRADE_ASSERT(_flags & Flag::DiffuseTexture, - "Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled", *this); - if(_lightCount) texture.bind(DiffuseTextureUnit); - return *this; -} - PhongGL& PhongGL::setSpecularColor(const Magnum::Color4& color) { if(_lightCount) setUniform(_specularColorUniform, color); return *this; } -PhongGL& PhongGL::bindSpecularTexture(GL::Texture2D& texture) { - CORRADE_ASSERT(_flags & Flag::SpecularTexture, - "Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled", *this); - if(_lightCount) texture.bind(SpecularTextureUnit); - return *this; -} - -PhongGL& PhongGL::bindNormalTexture(GL::Texture2D& texture) { - CORRADE_ASSERT(_flags & Flag::NormalTexture, - "Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled", *this); - if(_lightCount) texture.bind(NormalTextureUnit); - return *this; -} - -PhongGL& PhongGL::bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal) { - CORRADE_ASSERT(_flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture), - "Shaders::PhongGL::bindTextures(): the shader was not created with any textures enabled", *this); - GL::AbstractTexture::bind(AmbientTextureUnit, {ambient, diffuse, specular, normal}); - return *this; -} - PhongGL& PhongGL::setShininess(Float shininess) { if(_lightCount) setUniform(_shininessUniform, shininess); return *this; @@ -503,6 +468,41 @@ PhongGL& PhongGL::setLightRange(const UnsignedInt id, const Float range) { return *this; } +PhongGL& PhongGL::bindAmbientTexture(GL::Texture2D& texture) { + CORRADE_ASSERT(_flags & Flag::AmbientTexture, + "Shaders::PhongGL::bindAmbientTexture(): the shader was not created with ambient texture enabled", *this); + texture.bind(AmbientTextureUnit); + return *this; +} + +PhongGL& PhongGL::bindDiffuseTexture(GL::Texture2D& texture) { + CORRADE_ASSERT(_flags & Flag::DiffuseTexture, + "Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled", *this); + if(_lightCount) texture.bind(DiffuseTextureUnit); + return *this; +} + +PhongGL& PhongGL::bindSpecularTexture(GL::Texture2D& texture) { + CORRADE_ASSERT(_flags & Flag::SpecularTexture, + "Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled", *this); + if(_lightCount) texture.bind(SpecularTextureUnit); + return *this; +} + +PhongGL& PhongGL::bindNormalTexture(GL::Texture2D& texture) { + CORRADE_ASSERT(_flags & Flag::NormalTexture, + "Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled", *this); + if(_lightCount) texture.bind(NormalTextureUnit); + return *this; +} + +PhongGL& PhongGL::bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal) { + CORRADE_ASSERT(_flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture), + "Shaders::PhongGL::bindTextures(): the shader was not created with any textures enabled", *this); + GL::AbstractTexture::bind(AmbientTextureUnit, {ambient, diffuse, specular, normal}); + return *this; +} + Debug& operator<<(Debug& debug, const PhongGL::Flag value) { debug << "Shaders::PhongGL::Flag" << Debug::nospace; diff --git a/src/Magnum/Shaders/PhongGL.h b/src/Magnum/Shaders/PhongGL.h index 65d4990bc..177aeed60 100644 --- a/src/Magnum/Shaders/PhongGL.h +++ b/src/Magnum/Shaders/PhongGL.h @@ -604,6 +604,10 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { /** @brief Light count */ UnsignedInt lightCount() const { return _lightCount; } + /** @{ + * @name Uniform setters + */ + /** * @brief Set ambient color * @return Reference to self (for method chaining) @@ -615,17 +619,6 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { */ PhongGL& setAmbientColor(const Magnum::Color4& color); - /** - * @brief Bind an ambient texture - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::AmbientTexture - * enabled. - * @see @ref bindTextures(), @ref setAmbientColor(), - * @ref Shaders-PhongGL-lights-ambient - */ - PhongGL& bindAmbientTexture(GL::Texture2D& texture); - /** * @brief Set diffuse color * @return Reference to self (for method chaining) @@ -637,17 +630,6 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { */ PhongGL& setDiffuseColor(const Magnum::Color4& color); - /** - * @brief Bind a diffuse texture - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::DiffuseTexture - * enabled. If @ref lightCount() is zero, this function is a no-op, as - * diffuse color doesn't contribute to the output in that case. - * @see @ref bindTextures(), @ref setDiffuseColor() - */ - PhongGL& bindDiffuseTexture(GL::Texture2D& texture); - /** * @brief Set normal texture scale * @return Reference to self (for method chaining) @@ -666,20 +648,6 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { */ PhongGL& setNormalTextureScale(Float scale); - /** - * @brief Bind a normal texture - * @return Reference to self (for method chaining) - * @m_since{2019,10} - * - * Expects that the shader was created with @ref Flag::NormalTexture - * enabled and the @ref Tangent attribute was supplied. If - * @ref lightCount() is zero, this function is a no-op, as normals - * don't contribute to the output in that case. - * @see @ref Shaders-PhongGL-normal-mapping, - * @ref bindTextures(), @ref setNormalTextureScale() - */ - PhongGL& bindNormalTexture(GL::Texture2D& texture); - /** * @brief Set specular color * @return Reference to self (for method chaining) @@ -694,36 +662,6 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { */ PhongGL& setSpecularColor(const Magnum::Color4& color); - /** - * @brief Bind a specular texture - * @return Reference to self (for method chaining) - * - * Expects that the shader was created with @ref Flag::SpecularTexture - * enabled. If @ref lightCount() is zero, this function is a no-op, as - * specular color doesn't contribute to the output in that case. - * @see @ref bindTextures(), @ref setSpecularColor() - */ - PhongGL& bindSpecularTexture(GL::Texture2D& texture); - - /** - * @brief Bind textures - * @return Reference to self (for method chaining) - * - * A particular texture has effect only if particular texture flag from - * @ref PhongGL::Flag "Flag" is set, you can use @cpp nullptr @ce for - * the rest. Expects that the shader was created with at least one of - * @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture, - * @ref Flag::SpecularTexture or @ref Flag::NormalTexture enabled. More - * efficient than setting each texture separately. - * @see @ref bindAmbientTexture(), @ref bindDiffuseTexture(), - * @ref bindSpecularTexture(), @ref bindNormalTexture() - */ - PhongGL& bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal - #ifdef MAGNUM_BUILD_DEPRECATED - = nullptr - #endif - ); - /** * @brief Set shininess * @return Reference to self (for method chaining) @@ -1009,6 +947,84 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { */ PhongGL& setLightRange(UnsignedInt id, Float range); + /** + * @} + */ + + /** @{ + * @name Texture binding + */ + + /** + * @brief Bind a diffuse texture + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::DiffuseTexture + * enabled. If @ref lightCount() is zero, this function is a no-op, as + * diffuse color doesn't contribute to the output in that case. + * @see @ref bindTextures(), @ref setDiffuseColor() + */ + PhongGL& bindDiffuseTexture(GL::Texture2D& texture); + + /** + * @brief Bind an ambient texture + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::AmbientTexture + * enabled. + * @see @ref bindTextures(), @ref setAmbientColor(), + * @ref Shaders-PhongGL-lights-ambient + */ + PhongGL& bindAmbientTexture(GL::Texture2D& texture); + + /** + * @brief Bind a normal texture + * @return Reference to self (for method chaining) + * @m_since{2019,10} + * + * Expects that the shader was created with @ref Flag::NormalTexture + * enabled and the @ref Tangent attribute was supplied. If + * @ref lightCount() is zero, this function is a no-op, as normals + * don't contribute to the output in that case. + * @see @ref Shaders-PhongGL-normal-mapping, + * @ref bindTextures(), @ref setNormalTextureScale() + */ + PhongGL& bindNormalTexture(GL::Texture2D& texture); + + /** + * @brief Bind a specular texture + * @return Reference to self (for method chaining) + * + * Expects that the shader was created with @ref Flag::SpecularTexture + * enabled. If @ref lightCount() is zero, this function is a no-op, as + * specular color doesn't contribute to the output in that case. + * @see @ref bindTextures(), @ref setSpecularColor() + */ + PhongGL& bindSpecularTexture(GL::Texture2D& texture); + + /** + * @brief Bind textures + * @return Reference to self (for method chaining) + * + * A particular texture has effect only if particular texture flag from + * @ref PhongGL::Flag "Flag" is set, you can use @cpp nullptr @ce for + * the rest. Expects that the shader was created with at least one of + * @ref Flag::AmbientTexture, @ref Flag::DiffuseTexture, + * @ref Flag::SpecularTexture or @ref Flag::NormalTexture enabled. More + * efficient than setting each texture separately. + * @see @ref bindAmbientTexture(), @ref bindDiffuseTexture(), + * @ref bindSpecularTexture(), @ref bindNormalTexture() + */ + PhongGL& bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, GL::Texture2D* specular, GL::Texture2D* normal + #ifdef MAGNUM_BUILD_DEPRECATED + = nullptr + #endif + ); + + /** + * @} + */ + private: /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h index 8cca43e87..f8a8f0db1 100644 --- a/src/Magnum/Shaders/VectorGL.h +++ b/src/Magnum/Shaders/VectorGL.h @@ -150,6 +150,10 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public Ab */ Flags flags() const { return _flags; } + /** @{ + * @name Uniform setters + */ + /** * @brief Set transformation and projection matrix * @return Reference to self (for method chaining) @@ -187,6 +191,10 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public Ab */ VectorGL& setColor(const Color4& color); + /** + * @} + */ + #ifndef DOXYGEN_GENERATING_OUTPUT /* Overloads to remove WTF-factor from method chaining order */ VectorGL& bindVectorTexture(GL::Texture2D& texture) { diff --git a/src/Magnum/Shaders/VertexColorGL.h b/src/Magnum/Shaders/VertexColorGL.h index 5bbd17fdc..513312fba 100644 --- a/src/Magnum/Shaders/VertexColorGL.h +++ b/src/Magnum/Shaders/VertexColorGL.h @@ -135,6 +135,10 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ /** @brief Move assignment */ VertexColorGL& operator=(VertexColorGL&&) noexcept = default; + /** @{ + * @name Uniform setters + */ + /** * @brief Set transformation and projection matrix * @return Reference to self (for method chaining) @@ -143,6 +147,10 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ */ VertexColorGL& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); + /** + * @} + */ + private: /* Prevent accidentally calling irrelevant functions */ #ifndef MAGNUM_TARGET_GLES From 9f0a61e76ecc2c90c07310ebcca3bdeb53d4e84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 17 Apr 2021 20:08:05 +0200 Subject: [PATCH 146/161] Shaders: group things together also in GLSL sources. It was also becoming quite a mess in there. --- src/Magnum/Shaders/AbstractVector.vert | 6 ++ src/Magnum/Shaders/DistanceFieldVector.frag | 8 +++ src/Magnum/Shaders/Flat.frag | 20 +++++-- src/Magnum/Shaders/Flat.vert | 24 ++++++-- src/Magnum/Shaders/FullScreenTriangle.glsl | 2 + src/Magnum/Shaders/MeshVisualizer.frag | 22 ++++--- src/Magnum/Shaders/MeshVisualizer.geom | 19 ++++++- src/Magnum/Shaders/MeshVisualizer.vert | 14 ++++- src/Magnum/Shaders/Phong.frag | 63 ++++++++++++--------- src/Magnum/Shaders/Phong.vert | 6 ++ src/Magnum/Shaders/Vector.frag | 6 ++ src/Magnum/Shaders/VertexColor.frag | 4 ++ src/Magnum/Shaders/VertexColor.vert | 6 ++ 13 files changed, 150 insertions(+), 50 deletions(-) diff --git a/src/Magnum/Shaders/AbstractVector.vert b/src/Magnum/Shaders/AbstractVector.vert index 5b4bb7498..17cb41708 100644 --- a/src/Magnum/Shaders/AbstractVector.vert +++ b/src/Magnum/Shaders/AbstractVector.vert @@ -28,6 +28,8 @@ #define out varying #endif +/* Uniforms */ + #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 0) #endif @@ -58,6 +60,8 @@ uniform mediump mat3 textureMatrix ; #endif +/* Inputs */ + #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = POSITION_ATTRIBUTE_LOCATION) #endif @@ -74,6 +78,8 @@ layout(location = TEXTURECOORDINATES_ATTRIBUTE_LOCATION) #endif in mediump vec2 textureCoordinates; +/* Outputs */ + out mediump vec2 interpolatedTextureCoordinates; void main() { diff --git a/src/Magnum/Shaders/DistanceFieldVector.frag b/src/Magnum/Shaders/DistanceFieldVector.frag index d7c99d3af..78b1b89f0 100644 --- a/src/Magnum/Shaders/DistanceFieldVector.frag +++ b/src/Magnum/Shaders/DistanceFieldVector.frag @@ -29,6 +29,8 @@ #define texture texture2D #endif +/* Uniforms */ + #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 2) #endif @@ -61,14 +63,20 @@ uniform lowp float smoothness #endif ; +/* Textures */ + #ifdef EXPLICIT_TEXTURE_LAYER /* See AbstractVector.h for details about the ID */ layout(binding = 6) #endif uniform lowp sampler2D vectorTexture; +/* Inputs */ + in mediump vec2 interpolatedTextureCoordinates; +/* OUtput */ + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) diff --git a/src/Magnum/Shaders/Flat.frag b/src/Magnum/Shaders/Flat.frag index c49a20078..21d3fbf45 100644 --- a/src/Magnum/Shaders/Flat.frag +++ b/src/Magnum/Shaders/Flat.frag @@ -33,12 +33,7 @@ #define in varying #endif -#ifdef TEXTURED -#ifdef EXPLICIT_TEXTURE_LAYER -layout(binding = 0) -#endif -uniform lowp sampler2D textureData; -#endif +/* Uniforms */ #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 2) @@ -68,6 +63,17 @@ layout(location = 4) uniform highp uint objectId; /* defaults to zero */ #endif +/* Textures */ + +#ifdef TEXTURED +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 0) +#endif +uniform lowp sampler2D textureData; +#endif + +/* Inputs */ + #ifdef TEXTURED in mediump vec2 interpolatedTextureCoordinates; #endif @@ -80,6 +86,8 @@ in lowp vec4 interpolatedVertexColor; flat in highp uint interpolatedInstanceObjectId; #endif +/* Outputs */ + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) diff --git a/src/Magnum/Shaders/Flat.vert b/src/Magnum/Shaders/Flat.vert index 2611ff9ab..1c4305fc6 100644 --- a/src/Magnum/Shaders/Flat.vert +++ b/src/Magnum/Shaders/Flat.vert @@ -32,6 +32,8 @@ #define out varying #endif +/* Uniforms */ + #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 0) #endif @@ -62,6 +64,8 @@ uniform mediump mat3 textureMatrix ; #endif +/* Inputs */ + #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = POSITION_ATTRIBUTE_LOCATION) #endif @@ -78,8 +82,6 @@ in highp vec4 position; layout(location = TEXTURECOORDINATES_ATTRIBUTE_LOCATION) #endif in mediump vec2 textureCoordinates; - -out mediump vec2 interpolatedTextureCoordinates; #endif #ifdef VERTEX_COLOR @@ -87,8 +89,6 @@ out mediump vec2 interpolatedTextureCoordinates; layout(location = COLOR_ATTRIBUTE_LOCATION) #endif in lowp vec4 vertexColor; - -out lowp vec4 interpolatedVertexColor; #endif #ifdef INSTANCED_OBJECT_ID @@ -96,8 +96,6 @@ out lowp vec4 interpolatedVertexColor; layout(location = OBJECT_ID_ATTRIBUTE_LOCATION) #endif in highp uint instanceObjectId; - -flat out highp uint interpolatedInstanceObjectId; #endif #ifdef INSTANCED_TRANSFORMATION @@ -120,6 +118,20 @@ layout(location = TEXTURE_OFFSET_ATTRIBUTE_LOCATION) in mediump vec2 instancedTextureOffset; #endif +/* Outputs */ + +#ifdef TEXTURED +out mediump vec2 interpolatedTextureCoordinates; +#endif + +#ifdef VERTEX_COLOR +out lowp vec4 interpolatedVertexColor; +#endif + +#ifdef INSTANCED_OBJECT_ID +flat out highp uint interpolatedInstanceObjectId; +#endif + void main() { #ifdef TWO_DIMENSIONS gl_Position.xywz = vec4(transformationProjectionMatrix* diff --git a/src/Magnum/Shaders/FullScreenTriangle.glsl b/src/Magnum/Shaders/FullScreenTriangle.glsl index a989d1e5a..e7b4d974c 100644 --- a/src/Magnum/Shaders/FullScreenTriangle.glsl +++ b/src/Magnum/Shaders/FullScreenTriangle.glsl @@ -23,6 +23,8 @@ DEALINGS IN THE SOFTWARE. */ +/* Inputs */ + #if !defined(NEW_GLSL) || defined(DISABLE_GL_MAGNUM_shader_vertex_id) #ifndef NEW_GLSL #define in attribute diff --git a/src/Magnum/Shaders/MeshVisualizer.frag b/src/Magnum/Shaders/MeshVisualizer.frag index d4dc84417..c206409bd 100644 --- a/src/Magnum/Shaders/MeshVisualizer.frag +++ b/src/Magnum/Shaders/MeshVisualizer.frag @@ -44,6 +44,8 @@ #extension GL_NV_shader_noperspective_interpolation: require #endif +/* Uniforms */ + #if (defined(WIREFRAME_RENDERING) || defined(INSTANCED_OBJECT_ID) || defined(VERTEX_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID)) && !defined(TBN_DIRECTION) #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 1) @@ -95,13 +97,6 @@ uniform lowp float smoothness ; #endif -#if defined(INSTANCED_OBJECT_ID) || defined(VERTEX_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) -#ifdef EXPLICIT_TEXTURE_LAYER -layout(binding = 4) -#endif -uniform lowp sampler2D colorMapTexture; -#endif - #if defined(INSTANCED_OBJECT_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 6) @@ -115,6 +110,17 @@ uniform lowp vec2 colorMapOffsetScale #define colorMapScale colorMapOffsetScale.y #endif +/* Textures */ + +#if defined(INSTANCED_OBJECT_ID) || defined(VERTEX_ID) || defined(PRIMITIVE_ID) || defined(PRIMITIVE_ID_FROM_VERTEX_ID) +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 4) +#endif +uniform lowp sampler2D colorMapTexture; +#endif + +/* Inputs */ + #if defined(WIREFRAME_RENDERING) || defined(TBN_DIRECTION) #ifndef NO_GEOMETRY_SHADER #if !defined(GL_ES) || defined(GL_NV_shader_noperspective_interpolation) @@ -141,6 +147,8 @@ in lowp vec4 backgroundColor; in lowp vec4 lineColor; #endif +/* Outputs */ + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) diff --git a/src/Magnum/Shaders/MeshVisualizer.geom b/src/Magnum/Shaders/MeshVisualizer.geom index 71a581d2c..e5b65c426 100644 --- a/src/Magnum/Shaders/MeshVisualizer.geom +++ b/src/Magnum/Shaders/MeshVisualizer.geom @@ -34,6 +34,8 @@ #endif #endif +/* Uniforms */ + #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 5) #endif @@ -81,6 +83,8 @@ uniform lowp float smoothness ; #endif +/* Inputs */ + #ifdef TANGENT_DIRECTION in highp vec4 tangentEndpoint[]; #endif @@ -91,6 +95,18 @@ in highp vec4 bitangentEndpoint[]; in highp vec4 normalEndpoint[]; #endif +#ifdef INSTANCED_OBJECT_ID +flat in highp uint interpolatedVsInstanceObjectId[]; +#endif +#ifdef VERTEX_ID +in highp float interpolatedVsMappedVertexId[]; +#endif +#ifdef PRIMITIVE_ID_FROM_VERTEX_ID +flat in highp uint interpolatedVsPrimitiveId[]; +#endif + +/* Outputs */ + layout(triangle_strip, max_vertices = MAX_VERTICES) out; /* Interpolate in screen space (if possible) */ @@ -100,15 +116,12 @@ noperspective out lowp vec3 dist; #ifdef INSTANCED_OBJECT_ID -flat in highp uint interpolatedVsInstanceObjectId[]; flat out highp uint interpolatedInstanceObjectId; #endif #ifdef VERTEX_ID -in highp float interpolatedVsMappedVertexId[]; out highp float interpolatedMappedVertexId; #endif #ifdef PRIMITIVE_ID_FROM_VERTEX_ID -flat in highp uint interpolatedVsPrimitiveId[]; flat out highp uint interpolatedPrimitiveId; #endif diff --git a/src/Magnum/Shaders/MeshVisualizer.vert b/src/Magnum/Shaders/MeshVisualizer.vert index cbfe22518..a67ebc024 100644 --- a/src/Magnum/Shaders/MeshVisualizer.vert +++ b/src/Magnum/Shaders/MeshVisualizer.vert @@ -32,6 +32,8 @@ #define out varying #endif +/* Uniforms */ + #ifdef TWO_DIMENSIONS #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 0) @@ -95,6 +97,8 @@ uniform highp float lineLength ; #endif +/* Inputs */ + #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = POSITION_ATTRIBUTE_LOCATION) #endif @@ -135,8 +139,6 @@ layout(location = 4) in lowp float vertexIndex; #define gl_VertexID int(vertexIndex) #endif - -out vec3 barycentric; #endif #ifdef INSTANCED_OBJECT_ID @@ -144,7 +146,15 @@ out vec3 barycentric; layout(location = OBJECT_ID_ATTRIBUTE_LOCATION) #endif in highp uint instanceObjectId; +#endif + +/* Outputs */ +#if defined(WIREFRAME_RENDERING) && defined(NO_GEOMETRY_SHADER) +out vec3 barycentric; +#endif + +#ifdef INSTANCED_OBJECT_ID #ifdef NO_GEOMETRY_SHADER flat out highp uint interpolatedInstanceObjectId; #else diff --git a/src/Magnum/Shaders/Phong.frag b/src/Magnum/Shaders/Phong.frag index 1201c8a2f..7f276f0a7 100644 --- a/src/Magnum/Shaders/Phong.frag +++ b/src/Magnum/Shaders/Phong.frag @@ -37,12 +37,7 @@ #define const #endif -#ifdef AMBIENT_TEXTURE -#ifdef EXPLICIT_TEXTURE_LAYER -layout(binding = 0) -#endif -uniform lowp sampler2D ambientTexture; -#endif +/* Uniforms */ #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 4) @@ -58,12 +53,6 @@ uniform lowp vec4 ambientColor ; #if LIGHT_COUNT -#ifdef DIFFUSE_TEXTURE -#ifdef EXPLICIT_TEXTURE_LAYER -layout(binding = 1) -#endif -uniform lowp sampler2D diffuseTexture; -#endif #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 5) @@ -74,20 +63,6 @@ uniform lowp vec4 diffuseColor #endif ; -#ifdef SPECULAR_TEXTURE -#ifdef EXPLICIT_TEXTURE_LAYER -layout(binding = 2) -#endif -uniform lowp sampler2D specularTexture; -#endif - -#ifdef NORMAL_TEXTURE -#ifdef EXPLICIT_TEXTURE_LAYER -layout(binding = 3) -#endif -uniform lowp sampler2D normalTexture; -#endif - #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 6) #endif @@ -170,6 +145,40 @@ uniform lowp float lightRanges[LIGHT_COUNT] ; #endif +/* Textures */ + +#ifdef AMBIENT_TEXTURE +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 0) +#endif +uniform lowp sampler2D ambientTexture; +#endif + +#if LIGHT_COUNT +#ifdef DIFFUSE_TEXTURE +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 1) +#endif +uniform lowp sampler2D diffuseTexture; +#endif + +#ifdef SPECULAR_TEXTURE +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 2) +#endif +uniform lowp sampler2D specularTexture; +#endif + +#ifdef NORMAL_TEXTURE +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 3) +#endif +uniform lowp sampler2D normalTexture; +#endif +#endif + +/* Inputs */ + #if LIGHT_COUNT in mediump vec3 transformedNormal; #ifdef NORMAL_TEXTURE @@ -196,6 +205,8 @@ in lowp vec4 interpolatedVertexColor; flat in highp uint interpolatedInstanceObjectId; #endif +/* Outputs */ + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) diff --git a/src/Magnum/Shaders/Phong.vert b/src/Magnum/Shaders/Phong.vert index efcc5963c..80f48ce04 100644 --- a/src/Magnum/Shaders/Phong.vert +++ b/src/Magnum/Shaders/Phong.vert @@ -32,6 +32,8 @@ #define out varying #endif +/* Uniforms */ + #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 0) #endif @@ -84,6 +86,8 @@ uniform highp vec4 lightPositions[LIGHT_COUNT] ; #endif +/* Inputs */ + #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = POSITION_ATTRIBUTE_LOCATION) #endif @@ -162,6 +166,8 @@ layout(location = TEXTURE_OFFSET_ATTRIBUTE_LOCATION) in mediump vec2 instancedTextureOffset; #endif +/* Outputs */ + #if LIGHT_COUNT out mediump vec3 transformedNormal; #ifdef NORMAL_TEXTURE diff --git a/src/Magnum/Shaders/Vector.frag b/src/Magnum/Shaders/Vector.frag index 8904a5611..a10ac4931 100644 --- a/src/Magnum/Shaders/Vector.frag +++ b/src/Magnum/Shaders/Vector.frag @@ -29,6 +29,8 @@ #define texture texture2D #endif +/* Uniforms */ + #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 2) #endif @@ -49,8 +51,12 @@ layout(binding = 6) #endif uniform lowp sampler2D vectorTexture; +/* Inputs */ + in mediump vec2 interpolatedTextureCoordinates; +/* Outputs */ + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) diff --git a/src/Magnum/Shaders/VertexColor.frag b/src/Magnum/Shaders/VertexColor.frag index 31e796cd6..acf3a6ac7 100644 --- a/src/Magnum/Shaders/VertexColor.frag +++ b/src/Magnum/Shaders/VertexColor.frag @@ -28,8 +28,12 @@ #define fragmentColor gl_FragColor #endif +/* Inputs */ + in lowp vec4 interpolatedColor; +/* Outputs */ + #ifdef NEW_GLSL #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = COLOR_OUTPUT_ATTRIBUTE_LOCATION) diff --git a/src/Magnum/Shaders/VertexColor.vert b/src/Magnum/Shaders/VertexColor.vert index 434c89fda..fda6574e3 100644 --- a/src/Magnum/Shaders/VertexColor.vert +++ b/src/Magnum/Shaders/VertexColor.vert @@ -28,6 +28,8 @@ #define out varying #endif +/* Uniforms */ + #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 0) #endif @@ -47,6 +49,8 @@ uniform highp mat4 transformationProjectionMatrix #error #endif +/* Inputs */ + #ifdef EXPLICIT_ATTRIB_LOCATION layout(location = POSITION_ATTRIBUTE_LOCATION) #endif @@ -63,6 +67,8 @@ layout(location = COLOR_ATTRIBUTE_LOCATION) #endif in lowp vec4 color; +/* Outputs */ + out lowp vec4 interpolatedColor; void main() { From f74942f67a61fea0b04fecfc053480bd5972629f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 19 Apr 2021 09:15:40 +0200 Subject: [PATCH 147/161] Shaders: make the string building slightly less crazy. --- src/Magnum/Shaders/PhongGL.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index de4494706..ba0d0b308 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -94,9 +95,9 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): _flags{flags} lightPositionInitializerPreamble.size() + lightCount*(lightPositionInitializerItem.size())); - lightInitializerVertex.append(lightPositionInitializerPreamble.data(), lightPositionInitializerPreamble.size()); + lightInitializerVertex.append(lightPositionInitializerPreamble); for(std::size_t i = 0; i != lightCount; ++i) - lightInitializerVertex.append(lightPositionInitializerItem.data(), lightPositionInitializerItem.size()); + lightInitializerVertex.append(lightPositionInitializerItem); /* Drop the last comma and add a newline at the end */ lightInitializerVertex[lightInitializerVertex.size() - 2] = '\n'; @@ -108,17 +109,17 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): _flags{flags} lightCount*(lightColorInitializerItem.size() + lightRangeInitializerItem.size())); - lightInitializerFragment.append(lightColorInitializerPreamble.data(), lightColorInitializerPreamble.size()); + lightInitializerFragment.append(lightColorInitializerPreamble); for(std::size_t i = 0; i != lightCount; ++i) - lightInitializerFragment.append(lightColorInitializerItem.data(), lightColorInitializerItem.size()); + lightInitializerFragment.append(lightColorInitializerItem); /* Drop the last comma and add a newline at the end */ lightInitializerFragment[lightInitializerFragment.size() - 2] = '\n'; lightInitializerFragment.resize(lightInitializerFragment.size() - 1); - lightInitializerFragment.append(lightRangeInitializerPreamble.data(), lightRangeInitializerPreamble.size()); + lightInitializerFragment.append(lightRangeInitializerPreamble); for(std::size_t i = 0; i != lightCount; ++i) - lightInitializerFragment.append(lightRangeInitializerItem.data(), lightRangeInitializerItem.size()); + lightInitializerFragment.append(lightRangeInitializerItem); /* Drop the last comma and add a newline at the end */ lightInitializerFragment[lightInitializerFragment.size() - 2] = '\n'; From faed96b4cfc60a3d5d2e1fde3d143eb5363439da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 21 Apr 2021 12:47:10 +0200 Subject: [PATCH 148/161] Shaders: avoid repeated GL::Context::current() calls. It involves a TLS lookup each time and it's just unnecessary extra typing. --- src/Magnum/Shaders/DistanceFieldVectorGL.cpp | 12 ++++---- src/Magnum/Shaders/FlatGL.cpp | 12 ++++---- src/Magnum/Shaders/MeshVisualizerGL.cpp | 30 +++++++++++++------- src/Magnum/Shaders/PhongGL.cpp | 12 ++++---- src/Magnum/Shaders/VectorGL.cpp | 12 ++++---- src/Magnum/Shaders/VertexColorGL.cpp | 10 ++++--- 6 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp index 32c8e8795..1ce614bc3 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -48,10 +48,12 @@ template DistanceFieldVectorGL::DistanceFiel #endif Utility::Resource rs("MagnumShadersGL"); + const GL::Context& context = GL::Context::current(); + #ifndef MAGNUM_TARGET_GLES - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); + const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); #else - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); + const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); #endif GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); @@ -71,7 +73,7 @@ template DistanceFieldVectorGL::DistanceFiel /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { GL::AbstractShaderProgram::bindAttributeLocation(AbstractVectorGL::Position::Location, "position"); @@ -82,7 +84,7 @@ template DistanceFieldVectorGL::DistanceFiel CORRADE_INTERNAL_ASSERT_OUTPUT(GL::AbstractShaderProgram::link()); #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { _transformationProjectionMatrixUniform = GL::AbstractShaderProgram::uniformLocation("transformationProjectionMatrix"); @@ -95,7 +97,7 @@ template DistanceFieldVectorGL::DistanceFiel } #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { GL::AbstractShaderProgram::setUniform(GL::AbstractShaderProgram::uniformLocation("vectorTexture"), diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index bfd7b355a..cb054eaf9 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -56,10 +56,12 @@ template FlatGL::FlatGL(const Flags flags): #endif Utility::Resource rs("MagnumShadersGL"); + const GL::Context& context = GL::Context::current(); + #ifndef MAGNUM_TARGET_GLES - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); + const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); #else - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); + const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); #endif GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); @@ -94,7 +96,7 @@ template FlatGL::FlatGL(const Flags flags): bindFragmentDataLocation() */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { bindAttributeLocation(Position::Location, "position"); @@ -120,7 +122,7 @@ template FlatGL::FlatGL(const Flags flags): CORRADE_INTERNAL_ASSERT_OUTPUT(link()); #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); @@ -134,7 +136,7 @@ template FlatGL::FlatGL(const Flags flags): } #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { if(flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureUnit); diff --git a/src/Magnum/Shaders/MeshVisualizerGL.cpp b/src/Magnum/Shaders/MeshVisualizerGL.cpp index 2319626f5..ef34527af 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.cpp +++ b/src/Magnum/Shaders/MeshVisualizerGL.cpp @@ -96,16 +96,18 @@ MeshVisualizerGLBase::MeshVisualizerGLBase(FlagsBase flags): _flags{flags} { } GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& frag, const Utility::Resource& rs) const { + GL::Context& context = GL::Context::current(); + #ifndef MAGNUM_TARGET_GLES - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); + const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); /* Extended in MeshVisualizer3D for TBN visualization */ CORRADE_INTERNAL_ASSERT(!(_flags & FlagBase::Wireframe) || _flags & FlagBase::NoGeometryShader || version >= GL::Version::GL320); #elif !defined(MAGNUM_TARGET_WEBGL) - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GLES310, GL::Version::GLES300, GL::Version::GLES200}); + const GL::Version version = context.supportedVersion({GL::Version::GLES310, GL::Version::GLES300, GL::Version::GLES200}); /* Extended in MeshVisualizer3D for TBN visualization */ CORRADE_INTERNAL_ASSERT(!(_flags & FlagBase::Wireframe) || _flags & FlagBase::NoGeometryShader || version >= GL::Version::GLES310); #else - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); + const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); #endif vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); @@ -120,7 +122,7 @@ GL::Version MeshVisualizerGLBase::setupShaders(GL::Shader& vert, GL::Shader& fra #ifdef MAGNUM_TARGET_WEBGL .addSource("#define SUBSCRIPTING_WORKAROUND\n") #elif defined(MAGNUM_TARGET_GLES2) - .addSource(GL::Context::current().detectedDriver() & GL::Context::DetectedDriver::Angle ? + .addSource(context.detectedDriver() & GL::Context::DetectedDriver::Angle ? "#define SUBSCRIPTING_WORKAROUND\n" : "") #endif ; @@ -191,6 +193,10 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): Implementation::MeshV "Shaders::MeshVisualizerGL2D: at least Flag::Wireframe has to be enabled", ); #endif + #ifndef MAGNUM_TARGET_GLES + const GL::Context& context = GL::Context::current(); + #endif + Utility::Resource rs{"MagnumShadersGL"}; GL::Shader vert{NoCreate}; GL::Shader frag{NoCreate}; @@ -245,7 +251,7 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): Implementation::MeshV /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { bindAttributeLocation(Position::Location, "position"); @@ -255,7 +261,7 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): Implementation::MeshV #endif #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isVersionSupported(GL::Version::GL310)) + if(!context.isVersionSupported(GL::Version::GL310)) #endif { bindAttributeLocation(VertexIndex::Location, "vertexIndex"); @@ -267,7 +273,7 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): Implementation::MeshV CORRADE_INTERNAL_ASSERT_OUTPUT(link()); #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); @@ -352,6 +358,10 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): Implementation::MeshV "Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", ); #endif + #ifndef MAGNUM_TARGET_GLES + const GL::Context& context = GL::Context::current(); + #endif + Utility::Resource rs{"MagnumShadersGL"}; GL::Shader vert{NoCreate}; GL::Shader frag{NoCreate}; @@ -439,7 +449,7 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): Implementation::MeshV /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { bindAttributeLocation(Position::Location, "position"); @@ -460,7 +470,7 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): Implementation::MeshV #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isVersionSupported(GL::Version::GL310)) + if(!context.isVersionSupported(GL::Version::GL310)) #endif { bindAttributeLocation(VertexIndex::Location, "vertexIndex"); @@ -472,7 +482,7 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): Implementation::MeshV CORRADE_INTERNAL_ASSERT_OUTPUT(link()); #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { _transformationMatrixUniform = uniformLocation("transformationMatrix"); diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index ba0d0b308..750c6c2ad 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -67,10 +67,12 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): _flags{flags} #endif Utility::Resource rs("MagnumShadersGL"); + const GL::Context& context = GL::Context::current(); + #ifndef MAGNUM_TARGET_GLES - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); + const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); #else - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); + const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); #endif GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); @@ -177,7 +179,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): _flags{flags} bindFragmentDataLocation() */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { bindAttributeLocation(Position::Location, "position"); @@ -210,7 +212,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): _flags{flags} CORRADE_INTERNAL_ASSERT_OUTPUT(link()); #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { _transformationMatrixUniform = uniformLocation("transformationMatrix"); @@ -237,7 +239,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): _flags{flags} } #ifndef MAGNUM_TARGET_GLES - if(flags && !GL::Context::current().isExtensionSupported(version)) + if(flags && !context.isExtensionSupported(version)) #endif { if(flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"), AmbientTextureUnit); diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index d29cf4a1f..db401d3f4 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -48,10 +48,12 @@ template VectorGL::VectorGL(const Flags flag #endif Utility::Resource rs("MagnumShadersGL"); + const GL::Context& context = GL::Context::current(); + #ifndef MAGNUM_TARGET_GLES - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); + const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); #else - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); + const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); #endif GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); @@ -71,7 +73,7 @@ template VectorGL::VectorGL(const Flags flag /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { GL::AbstractShaderProgram::bindAttributeLocation(AbstractVectorGL::Position::Location, "position"); @@ -82,7 +84,7 @@ template VectorGL::VectorGL(const Flags flag CORRADE_INTERNAL_ASSERT_OUTPUT(GL::AbstractShaderProgram::link()); #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { _transformationProjectionMatrixUniform = GL::AbstractShaderProgram::uniformLocation("transformationProjectionMatrix"); @@ -93,7 +95,7 @@ template VectorGL::VectorGL(const Flags flag } #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { GL::AbstractShaderProgram::setUniform(GL::AbstractShaderProgram::uniformLocation("vectorTexture"), AbstractVectorGL::VectorTextureUnit); diff --git a/src/Magnum/Shaders/VertexColorGL.cpp b/src/Magnum/Shaders/VertexColorGL.cpp index 311ae603d..66ef23fc1 100644 --- a/src/Magnum/Shaders/VertexColorGL.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -47,10 +47,12 @@ template VertexColorGL::VertexColorGL() { #endif Utility::Resource rs("MagnumShadersGL"); + const GL::Context& context = GL::Context::current(); + #ifndef MAGNUM_TARGET_GLES - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); + const GL::Version version = context.supportedVersion({GL::Version::GL320, GL::Version::GL310, GL::Version::GL300, GL::Version::GL210}); #else - const GL::Version version = GL::Context::current().supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); + const GL::Version version = context.supportedVersion({GL::Version::GLES300, GL::Version::GLES200}); #endif GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); @@ -69,7 +71,7 @@ template VertexColorGL::VertexColorGL() { /* ES3 has this done in the shader directly */ #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { bindAttributeLocation(Position::Location, "position"); @@ -80,7 +82,7 @@ template VertexColorGL::VertexColorGL() { CORRADE_INTERNAL_ASSERT_OUTPUT(link()); #ifndef MAGNUM_TARGET_GLES - if(!GL::Context::current().isExtensionSupported(version)) + if(!context.isExtensionSupported(version)) #endif { _transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); From d683e26184c58bd4f8aed12b7096cfbb8932f2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 11 May 2021 13:57:35 +0200 Subject: [PATCH 149/161] Shaders: add a test to a proper IDE folder. --- src/Magnum/Shaders/Test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Magnum/Shaders/Test/CMakeLists.txt b/src/Magnum/Shaders/Test/CMakeLists.txt index 5e90c28f9..214681e51 100644 --- a/src/Magnum/Shaders/Test/CMakeLists.txt +++ b/src/Magnum/Shaders/Test/CMakeLists.txt @@ -36,6 +36,7 @@ corrade_add_test(ShadersVertexColorGL_Test VertexColorGL_Test.cpp LIBRARIES Magn set_target_properties( ShadersDistanceFieldVectorGL_Test ShadersFlatGL_Test + ShadersGenericGL_Test ShadersMeshVisualizerGL_Test ShadersPhongGL_Test ShadersVectorGL_Test From 1506c926f5a99094729a3b0f743fceb6ddbaa62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 11 May 2021 13:38:26 +0200 Subject: [PATCH 150/161] Shaders: doc++ --- src/Magnum/Shaders/DistanceFieldVectorGL.h | 4 ++-- src/Magnum/Shaders/FlatGL.h | 5 ++--- src/Magnum/Shaders/MeshVisualizerGL.h | 24 +++++++++++----------- src/Magnum/Shaders/VectorGL.h | 6 +++--- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.h b/src/Magnum/Shaders/DistanceFieldVectorGL.h index e588179a8..f4752b357 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.h +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.h @@ -204,8 +204,8 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector * outline starts. Initial value is @cpp 0.5f @ce, larger values will * make the vector art look thinner, smaller will make it look thicker. * - * The @p end parameter describes where outline ends. If set to value - * larger than @p start the outline is not drawn. Initial value is + * The @p end parameter describes where outline ends. If set to a value + * larger than @p start, the outline is not drawn. Initial value is * @cpp 1.0f @ce. * * @see @ref setOutlineColor() diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 8fa33dfb4..cf08d8362 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -443,9 +443,8 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: * @brief Set color * @return Reference to self (for method chaining) * - * If @ref Flag::Textured is set, initial value is - * @cpp 0xffffffff_rgbaf @ce and the color will be multiplied with the - * texture. + * Initial value is @cpp 0xffffffff_rgbaf @ce. If @ref Flag::Textured + * is set, the color will be multiplied with the texture. * @see @ref bindTexture() */ FlatGL& setColor(const Magnum::Color4& color); diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h index 6929bde97..949954a05 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.h +++ b/src/Magnum/Shaders/MeshVisualizerGL.h @@ -277,9 +277,9 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua * * Initial value is @cpp 0xffffffff_rgbaf @ce. Expects that either * @ref Flag::Wireframe or @ref Flag::InstancedObjectId / - * @ref Flag::PrimitiveId is enabled. In case of the latter, the color - * is multiplied with the color map coming from - * @ref bindColorMapTexture(). + * @ref Flag::PrimitiveId / @ref Flag::PrimitiveIdFromVertexId is + * enabled. In case of the latter, the color is multiplied with the + * color map coming from @ref bindColorMapTexture(). */ MeshVisualizerGL2D& setColor(const Color4& color) { return static_cast(Implementation::MeshVisualizerGLBase::setColor(color)); @@ -300,7 +300,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua * @brief Set wireframe width * @return Reference to self (for method chaining) * - * Value is in screen space (depending on @ref setViewportSize()), + * The value is in screen space (depending on @ref setViewportSize()), * initial value is @cpp 1.0f @ce. Expects that @ref Flag::Wireframe is * enabled. */ @@ -891,9 +891,9 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * * Initial value is @cpp 0xffffffff_rgbaf @ce. Expects that either * @ref Flag::Wireframe or @ref Flag::InstancedObjectId / - * @ref Flag::PrimitiveId is enabled. In case of the latter, the color - * is multiplied with the color map coming from - * @ref bindColorMapTexture(). + * @ref Flag::PrimitiveId / @ref Flag::PrimitiveIdFromVertexId is + * enabled. In case of the latter, the color is multiplied with the + * color map coming from @ref bindColorMapTexture(). */ MeshVisualizerGL3D& setColor(const Color4& color) { return static_cast(Implementation::MeshVisualizerGLBase::setColor(color)); @@ -914,7 +914,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * @brief Set wireframe width * @return Reference to self (for method chaining) * - * Value is in screen space (depending on @ref setViewportSize()), + * The value is in screen space (depending on @ref setViewportSize()), * initial value is @cpp 1.0f @ce. Expects that @ref Flag::Wireframe is * enabled. */ @@ -963,7 +963,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * @return Reference to self (for method chaining) * @m_since{2020,06} * - * Value is in screen space (depending on @ref setViewportSize()), + * The value is in screen space (depending on @ref setViewportSize()), * initial value is @cpp 1.0f @ce. Expects that * @ref Flag::TangentDirection, * @ref Flag::BitangentFromTangentDirection, @@ -982,8 +982,8 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * @return Reference to self (for method chaining) * @m_since{2020,06} * - * Value is in object space, initial value is @cpp 1.0f @ce. Expects - * that @ref Flag::TangentDirection, + * The value is in object space, initial value is @cpp 1.0f @ce. + * Expects that @ref Flag::TangentDirection, * @ref Flag::BitangentFromTangentDirection, * @ref Flag::BitangentDirection or @ref Flag::NormalDirection is * enabled. @@ -1000,7 +1000,7 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * @brief Set line smoothness * @return Reference to self (for method chaining) * - * Value is in screen space (depending on @ref setViewportSize()), + * The value is in screen space (depending on @ref setViewportSize()), * initial value is @cpp 2.0f @ce. Expects that @ref Flag::Wireframe, * @ref Flag::TangentDirection, * @ref Flag::BitangentFromTangentDirection, diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h index f8a8f0db1..d788f18d3 100644 --- a/src/Magnum/Shaders/VectorGL.h +++ b/src/Magnum/Shaders/VectorGL.h @@ -158,7 +158,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public Ab * @brief Set transformation and projection matrix * @return Reference to self (for method chaining) * - * Default is an identity matrix. + * Initial value is an identity matrix. */ VectorGL& setTransformationProjectionMatrix(const MatrixTypeFor& matrix); @@ -177,7 +177,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public Ab * @brief Set background color * @return Reference to self (for method chaining) * - * Default is @cpp 0x00000000_rgbaf @ce. + * Initial value is @cpp 0x00000000_rgbaf @ce. * @see @ref setColor() */ VectorGL& setBackgroundColor(const Color4& color); @@ -186,7 +186,7 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public Ab * @brief Set fill color * @return Reference to self (for method chaining) * - * Default is @cpp 0xffffffff_rgbaf @ce. + * Initial value is @cpp 0xffffffff_rgbaf @ce. * @see @ref setBackgroundColor() */ VectorGL& setColor(const Color4& color); From c8ccd8bc3780cf5c0043b5fe3b68c41a791e06c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 30 Apr 2021 19:10:56 +0200 Subject: [PATCH 151/161] Doc++ --- src/Magnum/Tags.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Magnum/Tags.h b/src/Magnum/Tags.h index 1069353d9..8c86a563d 100644 --- a/src/Magnum/Tags.h +++ b/src/Magnum/Tags.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Tag type @ref Magnum::NoInitT, @ref Magnum::NoCreateT, tag @ref Magnum::NoInit, @ref Magnum::NoCreate + * @brief Tag type @ref Magnum::NoInitT, @ref Magnum::NoCreateT, @ref Magnum::NoAllocateT, tag @ref Magnum::NoInit, @ref Magnum::NoCreate, @ref Magnum::NoAllocate */ #include From 3cd1813bc2389c537a8206f5f551f234ad268f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 30 Apr 2021 19:14:51 +0200 Subject: [PATCH 152/161] Add a DefaultInit tag. This one will overload the meaning of "default", so updating the docs accordingly. --- doc/changelog.dox | 2 ++ src/Magnum/Tags.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/doc/changelog.dox b/doc/changelog.dox index f6b54981e..55de0d867 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -41,6 +41,8 @@ See also: @subsection changelog-latest-new New features - New @ref NoAllocate constructor tag, to be used by the @ref Vk library +- New @ref DefaultInit constructor tag, simply an alias to the existing + @ref Corrade::DefaultInit tag - New @ref PixelFormat::Depth16Unorm, @relativeref{PixelFormat,Depth24Unorm}, @relativeref{PixelFormat,Depth32F}, @relativeref{PixelFormat,Stencil8UI}, @relativeref{PixelFormat,Depth16UnormStencil8UI}, diff --git a/src/Magnum/Tags.h b/src/Magnum/Tags.h index 8c86a563d..ea413e3c0 100644 --- a/src/Magnum/Tags.h +++ b/src/Magnum/Tags.h @@ -35,6 +35,21 @@ namespace Magnum { +/** +@brief Default initialization tag type +@m_since_latest + +Used to distinguish construction with default initialization. The actual +meaning of "default" may vary, see documentation of a particular API using this +tag for a detailed behavior description. +@see @ref DefaultInit +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +typedef Corrade::DefaultInitT DefaultInitT; +#else +using Corrade::DefaultInitT; +#endif + /** @brief No initialization tag type @m_since{2020,06} @@ -76,6 +91,20 @@ struct NoAllocateT { #endif }; +/** +@brief Default initialization tag +@m_since_latest + +Use for construction with default initialization. The actual meaning of +"default" may vary, see documentation of a particular API using this tag for +a detailed behavior description. +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +constexpr DefaultInitT DefaultInit{}; +#else +using Corrade::DefaultInit; +#endif + /** @brief No initialization tag @m_since{2020,06} From 7413d2053fd5146a02530f21b44a035871263a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 May 2021 15:50:08 +0200 Subject: [PATCH 153/161] Math: doc++ --- src/Magnum/Math/Matrix.h | 4 ++-- src/Magnum/Math/Matrix3.h | 2 +- src/Magnum/Math/Matrix4.h | 2 +- src/Magnum/Math/RectangularMatrix.h | 8 ++++---- src/Magnum/Math/Vector.h | 2 +- src/Magnum/Math/Vector2.h | 2 +- src/Magnum/Math/Vector3.h | 2 +- src/Magnum/Math/Vector4.h | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Magnum/Math/Matrix.h b/src/Magnum/Math/Matrix.h index 6fa8a068d..098640728 100644 --- a/src/Magnum/Math/Matrix.h +++ b/src/Magnum/Math/Matrix.h @@ -78,7 +78,7 @@ template class Matrix: public RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, Vector(value)} {} @@ -95,7 +95,7 @@ template class Matrix: public RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, value} {} /** - * @brief Construct from a matrix of adifferent type + * @brief Construct from a matrix of a different type * * Performs only default casting on the values, no rounding or * anything else. Example usage: diff --git a/src/Magnum/Math/Matrix3.h b/src/Magnum/Math/Matrix3.h index b1679ba7c..6124241e2 100644 --- a/src/Magnum/Math/Matrix3.h +++ b/src/Magnum/Math/Matrix3.h @@ -231,7 +231,7 @@ template class Matrix3: public Matrix3x3 { /** @copydoc Matrix::Matrix(const RectangularMatrix&) */ template constexpr explicit Matrix3(const RectangularMatrix<3, 3, U>& other) noexcept: Matrix3x3(other) {} - /** @brief Construct from external representation */ + /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit Matrix3(const U& other) noexcept: Matrix3x3(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {} /** diff --git a/src/Magnum/Math/Matrix4.h b/src/Magnum/Math/Matrix4.h index 2008ac00f..fe03d0709 100644 --- a/src/Magnum/Math/Matrix4.h +++ b/src/Magnum/Math/Matrix4.h @@ -464,7 +464,7 @@ template class Matrix4: public Matrix4x4 { /** @copydoc Matrix::Matrix(const RectangularMatrix&) */ template constexpr explicit Matrix4(const RectangularMatrix<4, 4, U>& other) noexcept: Matrix4x4(other) {} - /** @brief Construct from external representation */ + /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit Matrix4(const U& other): Matrix4x4(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(other)) {} /** diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index 583088325..64e5cdda1 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -139,7 +139,7 @@ template class RectangularMatrix { constexpr explicit RectangularMatrix(T value) noexcept: RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, value} {} /** - * @brief Construct matrix from another of different type + * @brief Construct from a matrix of a different type * * Performs only default casting on the values, no rounding or * anything else. Example usage: @@ -148,13 +148,13 @@ template class RectangularMatrix { */ template constexpr explicit RectangularMatrix(const RectangularMatrix& other) noexcept: RectangularMatrix(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other) {} - /** @brief Construct matrix from external representation */ + /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit RectangularMatrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} /** @brief Copy constructor */ constexpr /*implicit*/ RectangularMatrix(const RectangularMatrix&) noexcept = default; - /** @brief Convert matrix to external representation */ + /** @brief Convert a matrix to external representation */ template::to(std::declval>()))> constexpr explicit operator U() const { return Implementation::RectangularMatrixConverter::to(*this); } @@ -212,7 +212,7 @@ template class RectangularMatrix { } /** - * @brief Non-equality operator + * @brief Non-equality comparison * * @see @ref Vector::operator<(), @ref Vector::operator<=(), * @ref Vector::operator>=(), @ref Vector::operator>() diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index 1b911666a..5aac086ce 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -170,7 +170,7 @@ template class Vector { } /** - * @brief Pad vector + * @brief Pad a vector * * If size of @p a is smaller than @ref Size, it is padded from right * with @p value, otherwise it's cut. diff --git a/src/Magnum/Math/Vector2.h b/src/Magnum/Math/Vector2.h index 7e44cea14..2613a8009 100644 --- a/src/Magnum/Math/Vector2.h +++ b/src/Magnum/Math/Vector2.h @@ -129,7 +129,7 @@ template class Vector2: public Vector<2, T> { /** @copydoc Vector::Vector(const Vector&) */ template constexpr explicit Vector2(const Vector<2, U>& other) noexcept: Vector<2, T>(other) {} - /** @brief Construct vector from external representation */ + /** @brief Construct a vector from external representation */ template::from(std::declval())) diff --git a/src/Magnum/Math/Vector3.h b/src/Magnum/Math/Vector3.h index 7dd5b2248..aa77fc635 100644 --- a/src/Magnum/Math/Vector3.h +++ b/src/Magnum/Math/Vector3.h @@ -160,7 +160,7 @@ template class Vector3: public Vector<3, T> { /** @copydoc Vector::Vector(const Vector&) */ template constexpr explicit Vector3(const Vector<3, U>& other) noexcept: Vector<3, T>(other) {} - /** @brief Construct vector from external representation */ + /** @brief Construct a vector from external representation */ template::from(std::declval())) diff --git a/src/Magnum/Math/Vector4.h b/src/Magnum/Math/Vector4.h index 57b70df5d..7a64af83e 100644 --- a/src/Magnum/Math/Vector4.h +++ b/src/Magnum/Math/Vector4.h @@ -109,7 +109,7 @@ template class Vector4: public Vector<4, T> { fire! FFS. */ template constexpr explicit Vector4(const Vector<4, U>& other) noexcept: Vector<4, T>(other) {} - /** @brief Construct vector from external representation */ + /** @brief Construct a vector from external representation */ template::from(std::declval()))> constexpr explicit Vector4(const U& other): Vector<4, T>(Implementation::VectorConverter<4, T, U>::from(other)) {} /** @brief Copy constructor */ From a347a2b3bdee20422f78bf02c3e0cc052e74f4f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 May 2021 16:05:54 +0200 Subject: [PATCH 154/161] Math: make it possible to create an identity RectangularMatrix as well. --- doc/changelog.dox | 3 +++ src/Magnum/Math/Matrix.h | 2 +- src/Magnum/Math/RectangularMatrix.h | 22 +++++++++++++--- .../Math/Test/RectangularMatrixTest.cpp | 26 ++++++++++++++++--- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 55de0d867..971bdaec3 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -119,6 +119,9 @@ See also: create a transformation from a rotation and translation part (see [mosra/magnum#471](https://github.com/mosra/magnum/pull/471)) - Added @ref Math::Intersection::rayRange() (see [mosra/magnum#484](https://github.com/mosra/magnum/pull/484)) +- Added @ref Math::RectangularMatrix::RectangularMatrix(IdentityInitT, T) + constructor as it might be useful to create non-square identity matrices as + well @subsubsection changelog-latest-new-meshtools MeshTools library diff --git a/src/Magnum/Math/Matrix.h b/src/Magnum/Math/Matrix.h index 098640728..9487065a5 100644 --- a/src/Magnum/Math/Matrix.h +++ b/src/Magnum/Math/Matrix.h @@ -80,7 +80,7 @@ template class Matrix: public RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, Vector(value)} {} + constexpr explicit Matrix(IdentityInitT, T value = T(1)) noexcept: RectangularMatrix{IdentityInit, value} {} /** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT) */ constexpr explicit Matrix(ZeroInitT) noexcept: RectangularMatrix{ZeroInit} {} diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index 64e5cdda1..be3469295 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -124,9 +124,23 @@ template class RectangularMatrix { */ constexpr /*implicit*/ RectangularMatrix() noexcept: RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, ZeroInit} {} - /** @brief Construct a zero-filled matrix */ + /** + * @brief Construct a zero-filled matrix + * + * @see @ref RectangularMatrix(IdentityInitT, T) + */ constexpr explicit RectangularMatrix(ZeroInitT) noexcept: RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, ZeroInit} {} + /** + * @brief Construct an identity matrix + * @m_since_latest + * + * For non-square matrices, the diagonal has @ref DiagonalSize + * elements. The @p value allows you to specify a value on diagonal. + * @see @ref RectangularMatrix(ZeroInitT), @ref fromDiagonal() + */ + constexpr explicit RectangularMatrix(IdentityInitT, T value = T(1)) noexcept: RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, Vector(value)} {} + /** @brief Construct without initializing the contents */ explicit RectangularMatrix(Magnum::NoInitT) noexcept: RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, Magnum::NoInit} {} @@ -442,9 +456,6 @@ template class RectangularMatrix { #else private: #endif - /* Implementation for RectangularMatrix::fromDiagonal() and Matrix(IdentityInitT, T) */ - template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, const Vector& diagonal); - /* Implementation for RectangularMatrix::RectangularMatrix(T) and Matrix(T) */ /* MSVC 2015 can't handle {} here */ template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, T value) noexcept: _data{Vector((static_cast(sequence), value))...} {} @@ -455,6 +466,9 @@ template class RectangularMatrix { template friend class Matrix; template friend struct Implementation::MatrixDeterminant; + /* Implementation for RectangularMatrix::fromDiagonal() and RectangularMatrix(IdentityInitT, T) */ + template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, const Vector& diagonal); + /* Implementation for RectangularMatrix::RectangularMatrix(const RectangularMatrix&) */ template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& matrix) noexcept: _data{Vector(matrix[sequence])...} {} diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index b91c4fd78..948add31d 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -59,7 +59,8 @@ struct RectangularMatrixTest: Corrade::TestSuite::Tester { explicit RectangularMatrixTest(); void construct(); - void constructDefault(); + void constructZero(); + void constructIdentity(); void constructNoInit(); void constructOneValue(); void constructOneComponent(); @@ -112,7 +113,8 @@ typedef Vector<2, Int> Vector2i; RectangularMatrixTest::RectangularMatrixTest() { addTests({&RectangularMatrixTest::construct, - &RectangularMatrixTest::constructDefault, + &RectangularMatrixTest::constructZero, + &RectangularMatrixTest::constructIdentity, &RectangularMatrixTest::constructNoInit, &RectangularMatrixTest::constructOneValue, &RectangularMatrixTest::constructOneComponent, @@ -160,7 +162,7 @@ void RectangularMatrixTest::construct() { CORRADE_VERIFY(std::is_nothrow_constructible::value); } -void RectangularMatrixTest::constructDefault() { +void RectangularMatrixTest::constructZero() { constexpr Matrix4x3 a; constexpr Matrix4x3 b{ZeroInit}; CORRADE_COMPARE(a, Matrix4x3(Vector3(0.0f, 0.0f, 0.0f), @@ -179,6 +181,24 @@ void RectangularMatrixTest::constructDefault() { CORRADE_VERIFY(!std::is_convertible::value); } +void RectangularMatrixTest::constructIdentity() { + constexpr Matrix4x3 a{IdentityInit}; + constexpr Matrix4x3 b{IdentityInit, 4.0f}; + CORRADE_COMPARE(a, (Matrix4x3{Vector3{1.0f, 0.0f, 0.0f}, + Vector3{0.0f, 1.0f, 0.0f}, + Vector3{0.0f, 0.0f, 1.0f}, + Vector3{0.0f, 0.0f, 0.0f}})); + CORRADE_COMPARE(b, (Matrix4x3{Vector3{4.0f, 0.0f, 0.0f}, + Vector3{0.0f, 4.0f, 0.0f}, + Vector3{0.0f, 0.0f, 4.0f}, + Vector3{0.0f, 0.0f, 0.0f}})); + + CORRADE_VERIFY(std::is_nothrow_constructible::value); + + /* Implicit construction is not allowed */ + CORRADE_VERIFY(!std::is_convertible::value); +} + void RectangularMatrixTest::constructNoInit() { Matrix3x4 a{Vector4(1.0f, 2.0f, 3.0f, 4.0f), Vector4(5.0f, 6.0f, 7.0f, 8.0f), From 7072befbdb1dcbacdfe84dfaec27c316e73eb50e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 May 2021 17:07:39 +0200 Subject: [PATCH 155/161] Math: generalize slicing and expanding to arbitrarily-sized matrices. Originally was done only for square matrices, but now I need that for converting 3x3 -> 3x4 and back (UBO packing, ugh ugh), so let's generalize. --- doc/changelog.dox | 8 +++ src/Magnum/Math/Matrix.h | 27 ++++---- src/Magnum/Math/Matrix3.h | 17 +++-- src/Magnum/Math/Matrix4.h | 17 +++-- src/Magnum/Math/RectangularMatrix.h | 52 +++++++++++++++ src/Magnum/Math/Test/Matrix3Test.cpp | 39 ++++++----- src/Magnum/Math/Test/Matrix4Test.cpp | 46 +++++++------ src/Magnum/Math/Test/MatrixTest.cpp | 58 ++++++++-------- .../Math/Test/RectangularMatrixTest.cpp | 66 +++++++++++++++++++ 9 files changed, 242 insertions(+), 88 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 971bdaec3..0c74c5c3a 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -253,6 +253,14 @@ See also: - Added @ref Math::castInto() overloads for casting between @ref UnsignedByte and @ref UnsignedShort or @ref Byte and @ref Short, and for casting between @ref Float and @ref Double +- @ref Math::RectangularMatrix is now explicitly convertible from matrices of + different sizes, with a possibility to specify whether to fill the diagonal + or leave it as zeros. This was originally available only on (square) + @ref Math::Matrix from other square matrices where it implicitly filled the + diagonal to an identity, but is now generalized for arbitrary rectangular + matrices, and with the default on @ref Math::RectangularMatrix being + zero-fill while @ref Math::Matrix stays with the identity for consistency + with other constructors. @subsubsection changelog-latest-changes-meshtools MeshTools library diff --git a/src/Magnum/Math/Matrix.h b/src/Magnum/Math/Matrix.h index 9487065a5..53f749294 100644 --- a/src/Magnum/Math/Matrix.h +++ b/src/Magnum/Math/Matrix.h @@ -35,15 +35,6 @@ namespace Magnum { namespace Math { namespace Implementation { template struct MatrixDeterminant; - - template constexpr Vector valueOrIdentityVector(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other) { - return {(col < otherSize && row < otherSize ? other[col][row] : - col == row ? T{1} : T{0})...}; - } - - template constexpr Vector valueOrIdentityVector(const RectangularMatrix& other) { - return valueOrIdentityVector(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other); - } } /** @@ -107,14 +98,21 @@ template class Matrix: public RectangularMatrix::from(std::declval()))> constexpr explicit Matrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} + /** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix&, T) */ + template constexpr explicit Matrix(IdentityInitT, const RectangularMatrix& other, T value = T(1)) noexcept: RectangularMatrix{IdentityInit, other, value} {} + + /** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix&) */ + template constexpr explicit Matrix(ZeroInitT, const RectangularMatrix& other) noexcept: RectangularMatrix{ZeroInit, other} {} + /** * @brief Construct by slicing or expanding a matrix of different size + * @m_since_latest * - * If the other matrix is larger, takes only the first @cpp size @ce - * columns and rows from it; if the other matrix is smaller, it's - * expanded to an identity (ones on diagonal, zeros elsewhere). + * Equivalent to @ref Matrix(IdentityInitT, const RectangularMatrix&, T). + * Note that this default is different from @ref RectangularMatrix, + * where it's equivalent to the @ref ZeroInit variant instead. */ - template constexpr explicit Matrix(const RectangularMatrix& other) noexcept: Matrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other} {} + template constexpr explicit Matrix(const RectangularMatrix& other, T value = T(1)) noexcept: RectangularMatrix{IdentityInit, other, value} {} /** @brief Copy constructor */ constexpr /*implicit*/ Matrix(const RectangularMatrix& other) noexcept: RectangularMatrix(other) {} @@ -300,9 +298,6 @@ template class Matrix: public RectangularMatrix; - - /* Implementation for RectangularMatrix::RectangularMatrix(const RectangularMatrix&) */ - template constexpr explicit Matrix(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other) noexcept: RectangularMatrix{Implementation::valueOrIdentityVector(other)...} {} }; /** diff --git a/src/Magnum/Math/Matrix3.h b/src/Magnum/Math/Matrix3.h index 6124241e2..d988a1f30 100644 --- a/src/Magnum/Math/Matrix3.h +++ b/src/Magnum/Math/Matrix3.h @@ -234,14 +234,21 @@ template class Matrix3: public Matrix3x3 { /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit Matrix3(const U& other) noexcept: Matrix3x3(Implementation::RectangularMatrixConverter<3, 3, T, U>::from(other)) {} + /** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix&, T) */ + template constexpr explicit Matrix3(IdentityInitT, const RectangularMatrix& other, T value = T(1)) noexcept: Matrix3x3{IdentityInit, other, value} {} + + /** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix&) */ + template constexpr explicit Matrix3(ZeroInitT, const RectangularMatrix& other) noexcept: Matrix3x3{ZeroInit, other} {} + /** - * @brief Construct by slicing or expanding a matrix of a different size + * @brief Construct by slicing or expanding a matrix of different size + * @m_since_latest * - * If the other matrix is larger, takes only the first @cpp size @ce - * columns and rows from it; if the other matrix is smaller, it's - * expanded to an identity (ones on diagonal, zeros elsewhere). + * Equivalent to @ref Matrix3(IdentityInitT, const RectangularMatrix&, T). + * Note that this default is different from @ref RectangularMatrix, + * where it's equivalent to the @ref ZeroInit variant instead. */ - template constexpr explicit Matrix3(const RectangularMatrix& other) noexcept: Matrix3x3{other} {} + template constexpr explicit Matrix3(const RectangularMatrix& other, T value = T(1)) noexcept: Matrix3x3{IdentityInit, other, value} {} /** @brief Copy constructor */ constexpr /*implicit*/ Matrix3(const RectangularMatrix<3, 3, T>& other) noexcept: Matrix3x3(other) {} diff --git a/src/Magnum/Math/Matrix4.h b/src/Magnum/Math/Matrix4.h index fe03d0709..508152aa8 100644 --- a/src/Magnum/Math/Matrix4.h +++ b/src/Magnum/Math/Matrix4.h @@ -467,14 +467,21 @@ template class Matrix4: public Matrix4x4 { /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit Matrix4(const U& other): Matrix4x4(Implementation::RectangularMatrixConverter<4, 4, T, U>::from(other)) {} + /** @copydoc RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix&, T) */ + template constexpr explicit Matrix4(IdentityInitT, const RectangularMatrix& other, T value = T(1)) noexcept: Matrix4x4{IdentityInit, other, value} {} + + /** @copydoc RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix&) */ + template constexpr explicit Matrix4(ZeroInitT, const RectangularMatrix& other) noexcept: Matrix4x4{ZeroInit, other} {} + /** - * @brief Construct by slicing or expanding a matrix of a different size + * @brief Construct by slicing or expanding a matrix of different size + * @m_since_latest * - * If the other matrix is larger, takes only the first @cpp size @ce - * columns and rows from it; if the other matrix is smaller, it's - * expanded to an identity (ones on diagonal, zeros elsewhere). + * Equivalent to @ref Matrix4(IdentityInitT, const RectangularMatrix&, T). + * Note that this default is different from @ref RectangularMatrix, + * where it's equivalent to the @ref ZeroInit variant instead. */ - template constexpr explicit Matrix4(const RectangularMatrix& other) noexcept: Matrix4x4{other} {} + template constexpr explicit Matrix4(const RectangularMatrix& other, T value = T(1)) noexcept: Matrix4x4{IdentityInit, other, value} {} /** @brief Copy constructor */ constexpr /*implicit*/ Matrix4(const RectangularMatrix<4, 4, T>& other) noexcept: Matrix4x4(other) {} diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index be3469295..8a5671c5e 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -35,6 +35,23 @@ namespace Magnum { namespace Math { namespace Implementation { template struct RectangularMatrixConverter; + + template constexpr Vector valueOrZeroVector(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other) { + return {(col < otherCols && row < otherRows ? other[col][row] : T{0})...}; + } + + template constexpr Vector valueOrZeroVector(const RectangularMatrix& other) { + return valueOrZeroVector(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other); + } + + template constexpr Vector valueOrIdentityVector(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other, T value) { + return {(col < otherCols && row < otherRows ? other[col][row] : + col == row ? value : T{0})...}; + } + + template constexpr Vector valueOrIdentityVector(const RectangularMatrix& other, T value) { + return valueOrIdentityVector(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other, value); + } } /** @@ -162,6 +179,35 @@ template class RectangularMatrix { */ template constexpr explicit RectangularMatrix(const RectangularMatrix& other) noexcept: RectangularMatrix(typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other) {} + /** + * @brief Construct by slicing or expanding a matrix of different size, leaving the rest at zero + * @m_since_latest + * + * If the other matrix has less columns or rows, the corresponding + * vectors and components are set to zeros. + */ + template constexpr explicit RectangularMatrix(ZeroInitT, const RectangularMatrix& other) noexcept: RectangularMatrix{ZeroInit, typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other} {} + + /** + * @brief Construct by slicing or expanding a matrix of different size, leaving the rest at identity + * @m_since_latest + * + * If the other matrix has less columns or rows, the corresponding + * vectors and components are set to either zeros or @p value on the + * diagonal. + */ + template constexpr explicit RectangularMatrix(IdentityInitT, const RectangularMatrix& other, T value = T(1)) noexcept: RectangularMatrix{IdentityInit, typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other, value} {} + + /** + * @brief Construct by slicing or expanding a matrix of different size + * @m_since_latest + * + * Equivalent to @ref RectangularMatrix(ZeroInitT, const RectangularMatrix&). + * Note that this default is different from @ref Matrix, where it's + * equivalent to the @ref IdentityInit variant instead. + */ + template constexpr explicit RectangularMatrix(const RectangularMatrix& other) noexcept: RectangularMatrix{ZeroInit, typename Corrade::Containers::Implementation::GenerateSequence::Type{}, other} {} + /** @brief Construct a matrix from external representation */ template::from(std::declval()))> constexpr explicit RectangularMatrix(const U& other): RectangularMatrix(Implementation::RectangularMatrixConverter::from(other)) {} @@ -472,6 +518,12 @@ template class RectangularMatrix { /* Implementation for RectangularMatrix::RectangularMatrix(const RectangularMatrix&) */ template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, const RectangularMatrix& matrix) noexcept: _data{Vector(matrix[sequence])...} {} + /* Implementation for RectangularMatrix::RectangularMatrix(ZeroInitT, const RectangularMatrix&) */ + template constexpr explicit RectangularMatrix(ZeroInitT, Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other) noexcept: RectangularMatrix{Implementation::valueOrZeroVector(other)...} {} + + /* Implementation for RectangularMatrix::RectangularMatrix(IdentityInitT, const RectangularMatrix&) */ + template constexpr explicit RectangularMatrix(IdentityInitT, Corrade::Containers::Implementation::Sequence, const RectangularMatrix& other, T value) noexcept: RectangularMatrix{Implementation::valueOrIdentityVector(other, value)...} {} + /* Implementation for RectangularMatrix::RectangularMatrix(ZeroInitT) and RectangularMatrix::RectangularMatrix(NoInitT) */ /* MSVC 2015 can't handle {} here */ template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, U) noexcept: _data{Vector((static_cast(sequence), U{typename U::Init{}}))...} {} diff --git a/src/Magnum/Math/Test/Matrix3Test.cpp b/src/Magnum/Math/Test/Matrix3Test.cpp index 47014d65a..46999c503 100644 --- a/src/Magnum/Math/Test/Matrix3Test.cpp +++ b/src/Magnum/Math/Test/Matrix3Test.cpp @@ -105,10 +105,12 @@ struct Matrix3Test: Corrade::TestSuite::Tester { typedef Math::Deg Deg; typedef Math::Matrix2x2 Matrix2x2; +typedef Math::Matrix2x4 Matrix2x4; typedef Math::Matrix3 Matrix3; typedef Math::Matrix3 Matrix3i; typedef Math::Vector2 Vector2; typedef Math::Vector3 Vector3; +typedef Math::Vector<4, Float> Vector4; /* to avoid having to include Vector4 */ Matrix3Test::Matrix3Test() { addTests({&Matrix3Test::construct, @@ -251,22 +253,27 @@ void Matrix3Test::constructConversion() { } void Matrix3Test::constructFromDifferentSize() { - constexpr Matrix3 a{{3.0f, 5.0f, 8.0f}, - {4.5f, 4.0f, 7.0f}, - {1.0f, 2.0f, 3.0f}}; - constexpr Matrix2x2 b{Vector2{3.0f, 5.0f}, - Vector2{4.5f, 4.0f}}; - constexpr Matrix3 c{{3.0f, 5.0f, 0.0f}, - {4.5f, 4.0f, 0.0f}, - {0.0f, 0.0f, 1.0f}}; - - constexpr Matrix3 larger{b}; - CORRADE_COMPARE(larger, c); - CORRADE_COMPARE(Matrix3{b}, c); - - constexpr Matrix2x2 smaller{a}; - CORRADE_COMPARE(smaller, b); - CORRADE_COMPARE(Matrix2x2{a}, b); + /* Tested thoroughly in RectangularMatrixTest, verify just that the args + are propagated correctly (cols, rows, zero/identity, identity value) */ + constexpr Matrix2x4 a{Vector4{3.0f, 5.0f, 8.0f, -3.0f}, + Vector4{4.5f, 4.0f, 7.0f, 2.0f}}; + constexpr Matrix3 expectedIdentity{{3.0f, 5.0f, 8.0f}, + {4.5f, 4.0f, 7.0f}, + {0.0f, 0.0f, 0.5f}}; + constexpr Matrix3 expectedZero{{3.0f, 5.0f, 8.0f}, + {4.5f, 4.0f, 7.0f}, + {0.0f, 0.0f, 0.0f}}; + + constexpr Matrix3 identity1{a, 0.5f}; + constexpr Matrix3 identity2{IdentityInit, a, 0.5f}; + CORRADE_COMPARE(identity1, expectedIdentity); + CORRADE_COMPARE(identity2, expectedIdentity); + CORRADE_COMPARE((Matrix3{a, 0.5f}), expectedIdentity); + CORRADE_COMPARE((Matrix3{IdentityInit, a, 0.5f}), expectedIdentity); + + constexpr Matrix3 zero{ZeroInit, a}; + CORRADE_COMPARE(zero, expectedZero); + CORRADE_COMPARE((Matrix3{ZeroInit, a}), expectedZero); } void Matrix3Test::constructCopy() { diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index 63f01d3e3..553ade30b 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -122,8 +122,9 @@ struct Matrix4Test: Corrade::TestSuite::Tester { typedef Math::Deg Deg; typedef Math::Rad Rad; -typedef Math::Matrix<2, Float> Matrix2x2; -typedef Math::Matrix<3, Float> Matrix3x3; +typedef Math::Matrix2x2 Matrix2x2; +typedef Math::Matrix2x3 Matrix2x3; +typedef Math::Matrix3x3 Matrix3x3; typedef Math::Matrix4 Matrix4; typedef Math::Matrix4 Matrix4i; typedef Math::Vector2 Vector2; @@ -296,24 +297,29 @@ void Matrix4Test::constructConversion() { } void Matrix4Test::constructFromDifferentSize() { - constexpr Matrix4 a{{3.0f, 5.0f, 8.0f, -3.0f}, - {4.5f, 4.0f, 7.0f, 2.0f}, - {1.0f, 2.0f, 3.0f, -1.0f}, - {7.9f, -1.0f, 8.0f, -1.5f}}; - constexpr Matrix2x2 b{Vector2{3.0f, 5.0f}, - Vector2{4.5f, 4.0f}}; - constexpr Matrix4 c{{3.0f, 5.0f, 0.0f, 0.0f}, - {4.5f, 4.0f, 0.0f, 0.0f}, - {0.0f, 0.0f, 1.0f, 0.0f}, - {0.0f, 0.0f, 0.0f, 1.0f}}; - - constexpr Matrix4 larger{b}; - CORRADE_COMPARE(larger, c); - CORRADE_COMPARE(Matrix4{b}, c); - - constexpr Matrix2x2 smaller{a}; - CORRADE_COMPARE(smaller, b); - CORRADE_COMPARE(Matrix2x2{a}, b); + /* Tested thoroughly in RectangularMatrixTest, verify just that the args + are propagated correctly (cols, rows, zero/identity, identity value) */ + constexpr Matrix2x3 a{Vector3{3.0f, 5.0f, 8.0f}, + Vector3{4.5f, 4.0f, 7.0f}}; + constexpr Matrix4 expectedIdentity{{3.0f, 5.0f, 8.0f, 0.0f}, + {4.5f, 4.0f, 7.0f, 0.0f}, + {0.0f, 0.0f, 0.5f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.5f}}; + constexpr Matrix4 expectedZero{{3.0f, 5.0f, 8.0f, 0.0f}, + {4.5f, 4.0f, 7.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}}; + + constexpr Matrix4 identity1{a, 0.5f}; + constexpr Matrix4 identity2{IdentityInit, a, 0.5f}; + CORRADE_COMPARE(identity1, expectedIdentity); + CORRADE_COMPARE(identity2, expectedIdentity); + CORRADE_COMPARE((Matrix4{a, 0.5f}), expectedIdentity); + CORRADE_COMPARE((Matrix4{IdentityInit, a, 0.5f}), expectedIdentity); + + constexpr Matrix4 zero{ZeroInit, a}; + CORRADE_COMPARE(zero, expectedZero); + CORRADE_COMPARE((Matrix4{ZeroInit, a}), expectedZero); } void Matrix4Test::constructCopy() { diff --git a/src/Magnum/Math/Test/MatrixTest.cpp b/src/Magnum/Math/Test/MatrixTest.cpp index 6964a3655..40ad78569 100644 --- a/src/Magnum/Math/Test/MatrixTest.cpp +++ b/src/Magnum/Math/Test/MatrixTest.cpp @@ -89,14 +89,15 @@ struct MatrixTest: Corrade::TestSuite::Tester { void debug(); }; -typedef Matrix<2, Float> Matrix2x2; -typedef Matrix<3, Float> Matrix3x3; -typedef Matrix<4, Float> Matrix4x4; -typedef Matrix<4, Int> Matrix4x4i; -typedef Vector<2, Float> Vector2; -typedef Vector<3, Float> Vector3; -typedef Vector<4, Float> Vector4; -typedef Vector<4, Int> Vector4i; +typedef Math::Matrix2x2 Matrix2x2; +typedef Math::Matrix2x3 Matrix2x3; +typedef Math::Matrix3x3 Matrix3x3; +typedef Math::Matrix4x4 Matrix4x4; +typedef Math::Matrix4x4 Matrix4x4i; +typedef Math::Vector<2, Float> Vector2; +typedef Math::Vector<3, Float> Vector3; +typedef Math::Vector<4, Float> Vector4; +typedef Math::Vector<4, Int> Vector4i; typedef Math::Constants Constants; MatrixTest::MatrixTest() { @@ -248,24 +249,29 @@ void MatrixTest::constructConversion() { } void MatrixTest::constructFromDifferentSize() { - constexpr Matrix4x4 a{Vector4{3.0f, 5.0f, 8.0f, -3.0f}, - Vector4{4.5f, 4.0f, 7.0f, 2.0f}, - Vector4{1.0f, 2.0f, 3.0f, -1.0f}, - Vector4{7.9f, -1.0f, 8.0f, -1.5f}}; - constexpr Matrix2x2 b{Vector2{3.0f, 5.0f}, - Vector2{4.5f, 4.0f}}; - constexpr Matrix4x4 c{Vector4{3.0f, 5.0f, 0.0f, 0.0f}, - Vector4{4.5f, 4.0f, 0.0f, 0.0f}, - Vector4{0.0f, 0.0f, 1.0f, 0.0f}, - Vector4{0.0f, 0.0f, 0.0f, 1.0f}}; - - constexpr Matrix4x4 larger{b}; - CORRADE_COMPARE(larger, c); - CORRADE_COMPARE(Matrix4x4{b}, c); - - constexpr Matrix2x2 smaller{a}; - CORRADE_COMPARE(smaller, b); - CORRADE_COMPARE(Matrix2x2{a}, b); + /* Tested thoroughly in RectangularMatrixTest, verify just that the args + are propagated correctly (cols, rows, zero/identity, identity value) */ + constexpr Matrix2x3 a{Vector3{3.0f, 5.0f, 8.0f}, + Vector3{4.5f, 4.0f, 7.0f}}; + constexpr Matrix4x4 expectedIdentity{Vector4{3.0f, 5.0f, 8.0f, 0.0f}, + Vector4{4.5f, 4.0f, 7.0f, 0.0f}, + Vector4{0.0f, 0.0f, 0.5f, 0.0f}, + Vector4{0.0f, 0.0f, 0.0f, 0.5f}}; + constexpr Matrix4x4 expectedZero{Vector4{3.0f, 5.0f, 8.0f, 0.0f}, + Vector4{4.5f, 4.0f, 7.0f, 0.0f}, + Vector4{0.0f, 0.0f, 0.0f, 0.0f}, + Vector4{0.0f, 0.0f, 0.0f, 0.0f}}; + + constexpr Matrix4x4 identity1{a, 0.5f}; + constexpr Matrix4x4 identity2{IdentityInit, a, 0.5f}; + CORRADE_COMPARE(identity1, expectedIdentity); + CORRADE_COMPARE(identity2, expectedIdentity); + CORRADE_COMPARE((Matrix4x4{a, 0.5f}), expectedIdentity); + CORRADE_COMPARE((Matrix4x4{IdentityInit, a, 0.5f}), expectedIdentity); + + constexpr Matrix4x4 zero{ZeroInit, a}; + CORRADE_COMPARE(zero, expectedZero); + CORRADE_COMPARE((Matrix4x4{ZeroInit, a}), expectedZero); } void MatrixTest::constructCopy() { diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index 948add31d..63b4525c3 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -65,6 +65,7 @@ struct RectangularMatrixTest: Corrade::TestSuite::Tester { void constructOneValue(); void constructOneComponent(); void constructConversion(); + void constructFromDifferentSize(); void constructFromData(); void constructFromDiagonal(); void constructCopy(); @@ -98,8 +99,13 @@ struct RectangularMatrixTest: Corrade::TestSuite::Tester { }; typedef RectangularMatrix<4, 3, Float> Matrix4x3; +typedef RectangularMatrix<4, 2, Float> Matrix4x2; typedef RectangularMatrix<3, 4, Float> Matrix3x4; +typedef RectangularMatrix<3, 3, Float> Matrix3x3; +typedef RectangularMatrix<3, 2, Float> Matrix3x2; typedef RectangularMatrix<2, 2, Float> Matrix2x2; +typedef RectangularMatrix<2, 3, Float> Matrix2x3; +typedef RectangularMatrix<2, 4, Float> Matrix2x4; typedef RectangularMatrix<2, 2, Int> Matrix2x2i; typedef Vector<4, Float> Vector4; typedef Vector<3, Float> Vector3; @@ -119,6 +125,7 @@ RectangularMatrixTest::RectangularMatrixTest() { &RectangularMatrixTest::constructOneValue, &RectangularMatrixTest::constructOneComponent, &RectangularMatrixTest::constructConversion, + &RectangularMatrixTest::constructFromDifferentSize, &RectangularMatrixTest::constructFromData, &RectangularMatrixTest::constructFromDiagonal, &RectangularMatrixTest::constructCopy, @@ -260,6 +267,65 @@ void RectangularMatrixTest::constructConversion() { CORRADE_VERIFY(std::is_nothrow_constructible::value); } +void RectangularMatrixTest::constructFromDifferentSize() { + /* Test converting to more columns, less rows */ + constexpr Matrix2x4 a{Vector4{3.0f, 5.0f, 8.0f, -3.0f}, + Vector4{4.5f, 4.0f, 7.0f, 2.0f}}; + constexpr Matrix3x2 aExpected{Vector2{3.0f, 5.0f}, + Vector2{4.5f, 4.0f}, + Vector2{0.0f, 0.0f}}; + constexpr Matrix3x3 aExpectedZero{Vector3{3.0f, 5.0f, 8.0f}, + Vector3{4.5f, 4.0f, 7.0f}, + Vector3{0.0f, 0.0f, 0.0f}}; + constexpr Matrix3x3 aExpectedIdentity{Vector3{3.0f, 5.0f, 8.0f}, + Vector3{4.5f, 4.0f, 7.0f}, + Vector3{0.0f, 0.0f, 0.5f}}; + + constexpr Matrix3x2 a2{a}; + CORRADE_COMPARE(a2, aExpected); + CORRADE_COMPARE(Matrix3x2{a}, aExpected); + + constexpr Matrix3x3 aZero1{a}; + constexpr Matrix3x3 aZero2{ZeroInit, a}; + CORRADE_COMPARE(aZero1, aExpectedZero); + CORRADE_COMPARE(aZero2, aExpectedZero); + CORRADE_COMPARE(Matrix3x3{a}, aExpectedZero); + CORRADE_COMPARE((Matrix3x3{ZeroInit, a}), aExpectedZero); + + constexpr Matrix3x3 aIdentity{IdentityInit, a, 0.5f}; + CORRADE_COMPARE(aIdentity, aExpectedIdentity); + CORRADE_COMPARE((Matrix3x3{IdentityInit, aIdentity, 0.5f}), aExpectedIdentity); + + /* Test converting to less columns, more rows */ + constexpr Matrix4x2 b{Vector2{3.0f, 5.0f}, + Vector2{8.0f, -3.0f}, + Vector2{4.5f, 4.0f}, + Vector2{7.0f, 2.0f}}; + constexpr Matrix2x3 bExpected{Vector3{3.0f, 5.0f, 0.0f}, + Vector3{8.0f, -3.0f, 0.0f}}; + constexpr Matrix3x3 bExpectedZero{Vector3{3.0f, 5.0f, 0.0f}, + Vector3{8.0f, -3.0f, 0.0f}, + Vector3{4.5f, 4.0f, 0.0f}}; + constexpr Matrix3x3 bExpectedIdentity{Vector3{3.0f, 5.0f, 0.0f}, + Vector3{8.0f, -3.0f, 0.0f}, + Vector3{4.5f, 4.0f, 0.5f}}; + + constexpr Matrix2x3 b2{b}; + CORRADE_COMPARE(b2, bExpected); + CORRADE_COMPARE(Matrix2x3{b}, bExpected); + + constexpr Matrix3x3 bZero1{b}; + constexpr Matrix3x3 bZero2{ZeroInit, b}; + CORRADE_COMPARE(bZero1, bExpectedZero); + CORRADE_COMPARE(bZero2, bExpectedZero); + CORRADE_COMPARE(Matrix3x3{b}, bExpectedZero); + CORRADE_COMPARE((Matrix3x3{ZeroInit, b}), bExpectedZero); + + constexpr Matrix3x3 bIdentity{IdentityInit, b, 0.5f}; + CORRADE_COMPARE(bIdentity, bExpectedIdentity); + CORRADE_COMPARE((Matrix3x3{IdentityInit, bIdentity}), bExpectedIdentity); +} + void RectangularMatrixTest::constructFromData() { Float m[] = { 3.0f, 5.0f, 8.0f, 4.0f, From 08a6e7d957e651ee9063031a2ffd23abfa2648bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 May 2021 17:35:17 +0200 Subject: [PATCH 156/161] Math: explicit test that all types are trivially copyable. I saw some copy constructors here and there and wasn't sure. --- src/Magnum/Math/Test/AngleTest.cpp | 7 +++++++ src/Magnum/Math/Test/BezierTest.cpp | 5 +++++ src/Magnum/Math/Test/BoolVectorTest.cpp | 5 +++++ src/Magnum/Math/Test/ColorTest.cpp | 7 +++++++ src/Magnum/Math/Test/ComplexTest.cpp | 5 +++++ src/Magnum/Math/Test/CubicHermiteTest.cpp | 21 +++++++++++++++++-- src/Magnum/Math/Test/DualComplexTest.cpp | 5 +++++ src/Magnum/Math/Test/DualQuaternionTest.cpp | 5 +++++ src/Magnum/Math/Test/DualTest.cpp | 5 +++++ src/Magnum/Math/Test/FrustumTest.cpp | 5 +++++ src/Magnum/Math/Test/HalfTest.cpp | 5 +++++ src/Magnum/Math/Test/Matrix3Test.cpp | 5 +++++ src/Magnum/Math/Test/Matrix4Test.cpp | 5 +++++ src/Magnum/Math/Test/MatrixTest.cpp | 5 +++++ src/Magnum/Math/Test/QuaternionTest.cpp | 5 +++++ src/Magnum/Math/Test/RangeTest.cpp | 9 ++++++++ .../Math/Test/RectangularMatrixTest.cpp | 5 +++++ src/Magnum/Math/Test/UnitTest.cpp | 19 +++++++++++++++++ src/Magnum/Math/Test/Vector2Test.cpp | 5 +++++ src/Magnum/Math/Test/Vector3Test.cpp | 5 +++++ src/Magnum/Math/Test/Vector4Test.cpp | 5 +++++ src/Magnum/Math/Test/VectorTest.cpp | 5 +++++ 22 files changed, 146 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Math/Test/AngleTest.cpp b/src/Magnum/Math/Test/AngleTest.cpp index 2fce5c065..eead32ea1 100644 --- a/src/Magnum/Math/Test/AngleTest.cpp +++ b/src/Magnum/Math/Test/AngleTest.cpp @@ -33,6 +33,7 @@ #include #include #endif +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Angle.h" @@ -232,6 +233,12 @@ void AngleTest::constructCopy() { constexpr Radd d(b); CORRADE_COMPARE(d, b); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); diff --git a/src/Magnum/Math/Test/BezierTest.cpp b/src/Magnum/Math/Test/BezierTest.cpp index f87346dc8..84e74a536 100644 --- a/src/Magnum/Math/Test/BezierTest.cpp +++ b/src/Magnum/Math/Test/BezierTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Bezier.h" #include "Magnum/Math/CubicHermite.h" @@ -185,6 +186,10 @@ void BezierTest::constructCopy() { constexpr QuadraticBezier2D b{a}; CORRADE_COMPARE(b, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/BoolVectorTest.cpp b/src/Magnum/Math/Test/BoolVectorTest.cpp index 36510bb0a..667b22424 100644 --- a/src/Magnum/Math/Test/BoolVectorTest.cpp +++ b/src/Magnum/Math/Test/BoolVectorTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/BoolVector.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -176,6 +177,10 @@ void BoolVectorTest::constructCopy() { constexpr BoolVector19 b(a); CORRADE_COMPARE(b, BoolVector19(0xa5, 0x5f, 0x07)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/ColorTest.cpp b/src/Magnum/Math/Test/ColorTest.cpp index 1f5a74348..08f83b0e0 100644 --- a/src/Magnum/Math/Test/ColorTest.cpp +++ b/src/Magnum/Math/Test/ColorTest.cpp @@ -32,6 +32,7 @@ #include #include #endif +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Color.h" #include "Magnum/Math/Half.h" @@ -429,6 +430,12 @@ void ColorTest::constructCopy() { Color4 d(c); CORRADE_COMPARE(d, Color4(1.0f, 0.5f, 0.75f, 0.25f)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); diff --git a/src/Magnum/Math/Test/ComplexTest.cpp b/src/Magnum/Math/Test/ComplexTest.cpp index f6fe56efd..1b1a91f25 100644 --- a/src/Magnum/Math/Test/ComplexTest.cpp +++ b/src/Magnum/Math/Test/ComplexTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Complex.h" #include "Magnum/Math/Matrix3.h" @@ -253,6 +254,10 @@ void ComplexTest::constructCopy() { constexpr Complex b(a); CORRADE_COMPARE(b, Complex(2.5f, -5.0f)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/CubicHermiteTest.cpp b/src/Magnum/Math/Test/CubicHermiteTest.cpp index fa0394f63..5505e6de7 100644 --- a/src/Magnum/Math/Test/CubicHermiteTest.cpp +++ b/src/Magnum/Math/Test/CubicHermiteTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Bezier.h" #include "Magnum/Math/CubicHermite.h" @@ -588,6 +589,10 @@ void CubicHermiteTest::constructCopyScalar() { CORRADE_COMPARE(b, (CubicHermite1D{2.0f, -2.0f, -0.5f})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } @@ -598,6 +603,10 @@ void CubicHermiteTest::constructCopyVector() { CORRADE_COMPARE(b, (CubicHermite2D{{1.0f, 2.0f}, {1.5f, -2.0f}, {3.0f, -0.5f}})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } @@ -608,6 +617,10 @@ void CubicHermiteTest::constructCopyComplex() { CORRADE_COMPARE(b, (CubicHermiteComplex{{1.0f, 2.0f}, {1.5f, -2.0f}, {3.0f, -0.5f}})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } @@ -624,8 +637,12 @@ void CubicHermiteTest::constructCopyQuaternion() { {{1.5f, -2.0f, 0.1f}, 1.1f}, {{3.0f, -0.5f, 1.2f}, 0.3f}})); - CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); - CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } void CubicHermiteTest::dataScalar() { diff --git a/src/Magnum/Math/Test/DualComplexTest.cpp b/src/Magnum/Math/Test/DualComplexTest.cpp index 7acf807d5..7ab00ea04 100644 --- a/src/Magnum/Math/Test/DualComplexTest.cpp +++ b/src/Magnum/Math/Test/DualComplexTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/DualComplex.h" #include "Magnum/Math/DualQuaternion.h" @@ -246,6 +247,10 @@ void DualComplexTest::constructCopy() { DualComplex b(a); CORRADE_COMPARE(b, DualComplex({-1.0f, 2.5f}, {3.0f, -7.5f})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/DualQuaternionTest.cpp b/src/Magnum/Math/Test/DualQuaternionTest.cpp index 95c941c5a..9379c3ee2 100644 --- a/src/Magnum/Math/Test/DualQuaternionTest.cpp +++ b/src/Magnum/Math/Test/DualQuaternionTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/DualQuaternion.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -275,6 +276,10 @@ void DualQuaternionTest::constructCopy() { DualQuaternion b(a); CORRADE_COMPARE(b, DualQuaternion({{1.0f, 2.0f, -3.0f}, -3.5f}, {{4.5f, -7.0f, 2.0f}, 1.0f})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/DualTest.cpp b/src/Magnum/Math/Test/DualTest.cpp index b289c6c6b..cec3c7d81 100644 --- a/src/Magnum/Math/Test/DualTest.cpp +++ b/src/Magnum/Math/Test/DualTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Dual.h" #include "Magnum/Math/Quaternion.h" @@ -184,6 +185,10 @@ void DualTest::constructCopy() { constexpr Dual b(a); CORRADE_COMPARE(b, Dual(2.0f, 3.0f)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/FrustumTest.cpp b/src/Magnum/Math/Test/FrustumTest.cpp index e22e5ec7d..65618504c 100644 --- a/src/Magnum/Math/Test/FrustumTest.cpp +++ b/src/Magnum/Math/Test/FrustumTest.cpp @@ -29,6 +29,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Frustum.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -244,6 +245,10 @@ void FrustumTest::constructCopy() { constexpr Frustum b{a}; CORRADE_COMPARE(b, a); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/HalfTest.cpp b/src/Magnum/Math/Test/HalfTest.cpp index ce05e53ce..bf18ed16b 100644 --- a/src/Magnum/Math/Test/HalfTest.cpp +++ b/src/Magnum/Math/Test/HalfTest.cpp @@ -32,6 +32,7 @@ #if defined(DOXYGEN_GENERATING_OUTPUT) || defined(CORRADE_TARGET_UNIX) || (defined(CORRADE_TARGET_WINDOWS) && !defined(CORRADE_TARGET_WINDOWS_RT)) || defined(CORRADE_TARGET_EMSCRIPTEN) #include #endif +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Half.h" #include "Magnum/Math/Packing.h" @@ -562,6 +563,10 @@ void HalfTest::constructCopy() { CORRADE_COMPARE(b, Half{3.5f}); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/Matrix3Test.cpp b/src/Magnum/Math/Test/Matrix3Test.cpp index 46999c503..c4e7b193e 100644 --- a/src/Magnum/Math/Test/Matrix3Test.cpp +++ b/src/Magnum/Math/Test/Matrix3Test.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Matrix3.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -288,6 +289,10 @@ void Matrix3Test::constructCopy() { {4.5f, 4.0f, 7.0f}, {7.9f, -1.0f, 8.0f})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index 553ade30b..380b35a9d 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -27,6 +27,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Matrix4.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -336,6 +337,10 @@ void Matrix4Test::constructCopy() { {1.0f, 2.0f, 3.0f, -1.0f}, {7.9f, -1.0f, 8.0f, -1.5f})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/MatrixTest.cpp b/src/Magnum/Math/Test/MatrixTest.cpp index 40ad78569..f209e9339 100644 --- a/src/Magnum/Math/Test/MatrixTest.cpp +++ b/src/Magnum/Math/Test/MatrixTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Matrix.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -290,6 +291,10 @@ void MatrixTest::constructCopy() { CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif } void MatrixTest::convert() { diff --git a/src/Magnum/Math/Test/QuaternionTest.cpp b/src/Magnum/Math/Test/QuaternionTest.cpp index b31792c68..21ccd4ae8 100644 --- a/src/Magnum/Math/Test/QuaternionTest.cpp +++ b/src/Magnum/Math/Test/QuaternionTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Functions.h" #include "Magnum/Math/Matrix4.h" @@ -290,6 +291,10 @@ void QuaternionTest::constructCopy() { constexpr Quaternion b(a); CORRADE_COMPARE(b, Quaternion({1.0f, -3.0f, 7.0f}, 2.5f)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/RangeTest.cpp b/src/Magnum/Math/Test/RangeTest.cpp index d2b81823f..0a712bd47 100644 --- a/src/Magnum/Math/Test/RangeTest.cpp +++ b/src/Magnum/Math/Test/RangeTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/FunctionsBatch.h" #include "Magnum/Math/Range.h" @@ -343,6 +344,14 @@ void RangeTest::constructCopy() { CORRADE_COMPARE(e, Range2Di({3, 5}, {23, 78})); CORRADE_COMPARE(f, Range3Di({3, 5, -7}, {23, 78, 2})); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); diff --git a/src/Magnum/Math/Test/RectangularMatrixTest.cpp b/src/Magnum/Math/Test/RectangularMatrixTest.cpp index 63b4525c3..78f8402f9 100644 --- a/src/Magnum/Math/Test/RectangularMatrixTest.cpp +++ b/src/Magnum/Math/Test/RectangularMatrixTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/RectangularMatrix.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -366,6 +367,10 @@ void RectangularMatrixTest::constructCopy() { Vector4(5.0f, 6.0f, 7.0f, 8.0f), Vector4(9.0f, 10.0f, 11.0f, 12.0f))); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/UnitTest.cpp b/src/Magnum/Math/Test/UnitTest.cpp index d61b5925c..f698db8d2 100644 --- a/src/Magnum/Math/Test/UnitTest.cpp +++ b/src/Magnum/Math/Test/UnitTest.cpp @@ -25,6 +25,7 @@ #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Constants.h" #include "Magnum/Math/Unit.h" @@ -38,6 +39,8 @@ struct UnitTest: Corrade::TestSuite::Tester { void constructDefault(); void constructNoInit(); void constructConversion(); + void constructCopy(); + void compare(); void compareNaN(); @@ -51,6 +54,8 @@ UnitTest::UnitTest() { &UnitTest::constructDefault, &UnitTest::constructNoInit, &UnitTest::constructConversion, + &UnitTest::constructCopy, + &UnitTest::compare, &UnitTest::compareNaN, @@ -119,6 +124,20 @@ void UnitTest::constructConversion() { CORRADE_VERIFY(std::is_nothrow_constructible::value); } +void UnitTest::constructCopy() { + constexpr Sec a{25.0f}; + + constexpr Sec b{a}; + CORRADE_COMPARE(b, a); + + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif + CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); + CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); +} + void UnitTest::compare() { CORRADE_VERIFY(Sec(25.0f + TypeTraits::epsilon()/2.0f) == Sec(25.0f)); CORRADE_VERIFY(Sec(25.0f + TypeTraits::epsilon()*75.0f) != Sec(25.0f)); diff --git a/src/Magnum/Math/Test/Vector2Test.cpp b/src/Magnum/Math/Test/Vector2Test.cpp index 1865e16a1..e5e442b84 100644 --- a/src/Magnum/Math/Test/Vector2Test.cpp +++ b/src/Magnum/Math/Test/Vector2Test.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Vector3.h" /* Vector3 used in Vector2Test::cross() */ #include "Magnum/Math/StrictWeakOrdering.h" @@ -168,6 +169,10 @@ void Vector2Test::constructCopy() { Vector2 b(a); CORRADE_COMPARE(b, Vector2(1.5f, 2.5f)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/Vector3Test.cpp b/src/Magnum/Math/Test/Vector3Test.cpp index 51fd057b8..a1d7a58ba 100644 --- a/src/Magnum/Math/Test/Vector3Test.cpp +++ b/src/Magnum/Math/Test/Vector3Test.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Vector3.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -176,6 +177,10 @@ void Vector3Test::constructCopy() { Vector3 b(a); CORRADE_COMPARE(b, Vector3(1.0f, 2.5f, -3.0f)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/Vector4Test.cpp b/src/Magnum/Math/Test/Vector4Test.cpp index 4fc6e503a..356a64750 100644 --- a/src/Magnum/Math/Test/Vector4Test.cpp +++ b/src/Magnum/Math/Test/Vector4Test.cpp @@ -26,6 +26,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Vector4.h" #include "Magnum/Math/StrictWeakOrdering.h" @@ -197,6 +198,10 @@ void Vector4Test::constructCopy() { Vector4 b(a); CORRADE_COMPARE(b, Vector4(1.0f, -2.5f, 3.0f, 4.1f)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } diff --git a/src/Magnum/Math/Test/VectorTest.cpp b/src/Magnum/Math/Test/VectorTest.cpp index 509a6e34b..41b667ef3 100644 --- a/src/Magnum/Math/Test/VectorTest.cpp +++ b/src/Magnum/Math/Test/VectorTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include /* CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED */ #include "Magnum/Math/Half.h" #include "Magnum/Math/Vector.h" @@ -291,6 +292,10 @@ void VectorTest::constructCopy() { constexpr Vector4 b(a); CORRADE_COMPARE(b, Vector4(1.0f, 3.5f, 4.0f, -2.7f)); + #ifdef CORRADE_STD_IS_TRIVIALLY_TRAITS_SUPPORTED + CORRADE_VERIFY(std::is_trivially_copy_constructible::value); + CORRADE_VERIFY(std::is_trivially_copy_assignable::value); + #endif CORRADE_VERIFY(std::is_nothrow_copy_constructible::value); CORRADE_VERIFY(std::is_nothrow_copy_assignable::value); } From 57ae596d887a4574bdac51c199d5ee38f9afa4ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 2 May 2021 17:37:49 +0200 Subject: [PATCH 157/161] Math: don't call into RectangularMatrix privates from Matrix. Yes, it's one function call more this way, but it's cleaner and without duplicated code that's prone to bugs. --- src/Magnum/Math/Matrix.h | 2 +- src/Magnum/Math/RectangularMatrix.h | 13 ++++--------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Magnum/Math/Matrix.h b/src/Magnum/Math/Matrix.h index 53f749294..3b328e32d 100644 --- a/src/Magnum/Math/Matrix.h +++ b/src/Magnum/Math/Matrix.h @@ -83,7 +83,7 @@ template class Matrix: public RectangularMatrix constexpr /*implicit*/ Matrix(const Vector& first, const U&... next) noexcept: RectangularMatrix(first, next...) {} /** @brief Construct with one value for all elements */ - constexpr explicit Matrix(T value) noexcept: RectangularMatrix{typename Corrade::Containers::Implementation::GenerateSequence::Type{}, value} {} + constexpr explicit Matrix(T value) noexcept: RectangularMatrix{value} {} /** * @brief Construct from a matrix of a different type diff --git a/src/Magnum/Math/RectangularMatrix.h b/src/Magnum/Math/RectangularMatrix.h index 8a5671c5e..a7c56fd0d 100644 --- a/src/Magnum/Math/RectangularMatrix.h +++ b/src/Magnum/Math/RectangularMatrix.h @@ -497,21 +497,16 @@ template class RectangularMatrix { return *reinterpret_cast*>(data()); } - #ifndef DOXYGEN_GENERATING_OUTPUT - protected: - #else - private: - #endif - /* Implementation for RectangularMatrix::RectangularMatrix(T) and Matrix(T) */ - /* MSVC 2015 can't handle {} here */ - template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, T value) noexcept: _data{Vector((static_cast(sequence), value))...} {} - private: /* These two needed to access _data to speed up debug builds, Matrix::ij() needs access to different Matrix sizes */ template friend class Matrix; template friend struct Implementation::MatrixDeterminant; + /* Implementation for RectangularMatrix::RectangularMatrix(T) and Matrix(T) */ + /* MSVC 2015 can't handle {} here */ + template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, T value) noexcept: _data{Vector((static_cast(sequence), value))...} {} + /* Implementation for RectangularMatrix::fromDiagonal() and RectangularMatrix(IdentityInitT, T) */ template constexpr explicit RectangularMatrix(Corrade::Containers::Implementation::Sequence, const Vector& diagonal); From 047e8e6670e2c10300686d90355b96e0018c14d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 11 May 2021 13:35:50 +0200 Subject: [PATCH 158/161] GL: fix argument order in OpenGLTester::addBenchmarks(). Apparently I didn't use this overload yet. --- doc/changelog.dox | 4 ++++ src/Magnum/GL/OpenGLTester.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 0c74c5c3a..5f35b0a00 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -381,6 +381,10 @@ See also: - @ref GL::Context move constructor was not marked @cpp noexcept @ce by accident and it was also not really moving everything properly, especially when delayed creation was done on the moved-to object +- @ref GL::OpenGLTester::addBenchmarks() taking a setup/teardown function + passed the arguments to the base @relativeref{Corrade,TestSuite::Tester} + implementation in a wrong order, failing to compile if this function was + used in a test - @ref GL::Renderer::MemoryBarrier::ShaderStorage had an incorrect value - @ref GL::Shader limit queries for a particular shader stage on desktop were out-of-bounds array accesses, causing wrong or random values being returned diff --git a/src/Magnum/GL/OpenGLTester.h b/src/Magnum/GL/OpenGLTester.h index cf13f9aa0..353033e48 100644 --- a/src/Magnum/GL/OpenGLTester.h +++ b/src/Magnum/GL/OpenGLTester.h @@ -245,7 +245,7 @@ class OpenGLTester: public TestSuite::Tester { */ template void addBenchmarks(std::initializer_list benchmarks, std::size_t batchCount, void(Derived::*setup)(), void(Derived::*teardown)(), BenchmarkType benchmarkType = BenchmarkType::Default) { if(benchmarkType == BenchmarkType::GpuTime) - addCustomBenchmarks(benchmarks, batchCount, &OpenGLTester::gpuTimeBenchmarkBegin, &OpenGLTester::gpuTimeBenchmarkEnd, setup, teardown, BenchmarkUnits::Nanoseconds); + addCustomBenchmarks(benchmarks, batchCount, setup, teardown, &OpenGLTester::gpuTimeBenchmarkBegin, &OpenGLTester::gpuTimeBenchmarkEnd, BenchmarkUnits::Nanoseconds); else Tester::addBenchmarks(benchmarks, batchCount, setup, teardown, Tester::BenchmarkType(Int(benchmarkType))); } From 6f8ad66a907ae11a8a1774a86d129226be08c8bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 11 May 2021 13:37:06 +0200 Subject: [PATCH 159/161] sceneconverter: list also animations in --info. --- doc/changelog.dox | 4 +- src/Magnum/MeshTools/sceneconverter.cpp | 57 ++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index 5f35b0a00..0ce99357e 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -266,8 +266,8 @@ See also: - Added a `--bounds` option to @ref magnum-sceneconverter "magnum-sceneconverter", showing data ranges of known attributes -- @ref magnum-sceneconverter "magnum-sceneconverter" now lists also lights, - materials and textures in `--info` +- @ref magnum-sceneconverter "magnum-sceneconverter" now lists also + animations, lights, materials and textures in `--info` @subsubsection changelog-latest-changes-platform Platform libraries diff --git a/src/Magnum/MeshTools/sceneconverter.cpp b/src/Magnum/MeshTools/sceneconverter.cpp index fcb3f58c6..be9639758 100644 --- a/src/Magnum/MeshTools/sceneconverter.cpp +++ b/src/Magnum/MeshTools/sceneconverter.cpp @@ -40,6 +40,7 @@ #include "Magnum/Math/FunctionsBatch.h" #include "Magnum/MeshTools/RemoveDuplicates.h" #include "Magnum/Trade/AbstractImporter.h" +#include "Magnum/Trade/AnimationData.h" #include "Magnum/Trade/LightData.h" #include "Magnum/Trade/MaterialData.h" #include "Magnum/Trade/MeshData.h" @@ -282,6 +283,12 @@ used.)") return 0; } + struct AnimationInfo { + UnsignedInt animation; + Trade::AnimationData data{{}, {}}; + std::string name; + }; + struct LightInfo { UnsignedInt light; UnsignedInt references; @@ -346,8 +353,28 @@ used.)") } } - /* Light properties */ + /* Animation properties */ bool error = false; + Containers::Array animationInfos; + for(UnsignedInt i = 0; i != importer->animationCount(); ++i) { + Containers::Optional animation; + { + Duration d{importTime}; + if(!(animation = importer->animation(i))) { + error = true; + continue; + } + } + + AnimationInfo info{}; + info.animation = i; + info.name = importer->animationName(i); + info.data = *std::move(animation); + + arrayAppend(animationInfos, std::move(info)); + } + + /* Light properties */ Containers::Array lightInfos; for(UnsignedInt i = 0; i != importer->lightCount(); ++i) { Containers::Optional light; @@ -514,6 +541,34 @@ used.)") Containers::Array imageInfos = Trade::Implementation::imageInfo(*importer, error, compactImages); + for(const AnimationInfo& info: animationInfos) { + Debug d; + d << "Animation" << info.animation << Debug::nospace << ":"; + if(!info.name.empty()) d << info.name; + + d << Debug::newline << " Duration:" << info.data.duration(); + + for(UnsignedInt i = 0; i != info.data.trackCount(); ++i) { + d << Debug::newline << " Track" << i << Debug::nospace << ":" + << info.data.trackType(i); + if(info.data.trackType(i) != info.data.trackResultType(i)) + d << "->" << info.data.trackResultType(i); + d << Debug::nospace << "," << info.data.track(i).size() + << "keyframes"; + if(info.data.track(i).duration() != info.data.duration()) + d << Debug::nospace << "," << info.data.track(i).duration(); + d << Debug::newline << " " + << info.data.track(i).interpolation(); + d << Debug::newline << " " + << info.data.track(i).before() << Debug::nospace << "," + << info.data.track(i).after(); + d << Debug::newline << " Target: object" + << info.data.trackTarget(i) << Debug::nospace << "," + << info.data.trackTargetType(i); + /** @todo might be useful to show bounds here as well, though + not so much for things like complex numbers or quats */ + } + } for(const LightInfo& info: lightInfos) { Debug d; d << "Light" << info.light; From d03cc34385e166ed1675aaa038e8b1ea5e9992b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 11 May 2021 13:51:01 +0200 Subject: [PATCH 160/161] Platform: update docs about the EGL enumeration failing bug. It was actually a problem in glvnd, and got fixed in 1.3.3, so I don't need to do this env var gymnastic anymore. --- .../Platform/WindowlessEglApplication.h | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Magnum/Platform/WindowlessEglApplication.h b/src/Magnum/Platform/WindowlessEglApplication.h index 7aa6d7888..1eaf0fbe5 100644 --- a/src/Magnum/Platform/WindowlessEglApplication.h +++ b/src/Magnum/Platform/WindowlessEglApplication.h @@ -556,10 +556,8 @@ same can be also specified via via @ref Configuration::setCudaDevice(). @par No EGL devices found @parblock -Systems running Mesa 19.2 (which has the above extensions) that also have -`libEGL_nvidia.so` installed (for example as a CUDA dependency) may fail -to create the context with the following error (with additional output -produced when the `--magnum-gpu-validation` +With GLVND versions 1.3.2 and older, EGL context creation may fail with the +following error (with additional output produced when the `--magnum-gpu-validation` @ref GL-Context-usage-command-line "command-line option" is enabled): @m_class{m-console-wrap} @@ -570,12 +568,15 @@ eglQueryDevicesEXT(): EGL_BAD_ALLOC error: In function eglQueryDevicesEXT(), bac Platform::WindowlessEglApplication::tryCreateContext(): no EGL devices found @endcode -This is due to the NVidia's EGL implementation failing to enumerate devices -(because there aren't any), which then causes the GLVND wrapper to stop -instead of enumerating the Mesa devices as well. The solution is -whitelisting all EGL implementations except the NVidia one -as described in the libglvnd documentation -using the `__EGL_VENDOR_LIBRARY_FILENAMES` environment variable, for example: +This is due to some driver implementations failing to enumerate devices (for +example when the system has NVidia drivers installed as a dependency of CUDA +but there actually isn't any NVidia card) and the GLVND treats that as a fatal +error. This is [fixed in version 1.3.3](https://github.com/NVIDIA/libglvnd/commit/a527411da713b2068974c46d7129326520dc5923) +where it just skips that particular vendor and continues. A workaround on older +versions might be filtering out the bad devices manually using the +`__EGL_VENDOR_LIBRARY_FILENAMES` environment variable +as described in the libglvnd documentation, for +example: @m_class{m-console-wrap} From dd3ce93888ada70074d63d72c5998d950fa2eba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 11 May 2021 14:25:05 +0200 Subject: [PATCH 161/161] Math: MSVC 2015, you ICEd. --- src/Magnum/Math/Test/Matrix4Test.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Magnum/Math/Test/Matrix4Test.cpp b/src/Magnum/Math/Test/Matrix4Test.cpp index 380b35a9d..04aa9d193 100644 --- a/src/Magnum/Math/Test/Matrix4Test.cpp +++ b/src/Magnum/Math/Test/Matrix4Test.cpp @@ -312,13 +312,19 @@ void Matrix4Test::constructFromDifferentSize() { {0.0f, 0.0f, 0.0f, 0.0f}}; constexpr Matrix4 identity1{a, 0.5f}; - constexpr Matrix4 identity2{IdentityInit, a, 0.5f}; + #ifndef CORRADE_MSVC2015_COMPATIBILITY /* It ICEs, haha */ + constexpr + #endif + Matrix4 identity2{IdentityInit, a, 0.5f}; CORRADE_COMPARE(identity1, expectedIdentity); CORRADE_COMPARE(identity2, expectedIdentity); CORRADE_COMPARE((Matrix4{a, 0.5f}), expectedIdentity); CORRADE_COMPARE((Matrix4{IdentityInit, a, 0.5f}), expectedIdentity); - constexpr Matrix4 zero{ZeroInit, a}; + #ifndef CORRADE_MSVC2015_COMPATIBILITY /* It ICEs, haha */ + constexpr + #endif + Matrix4 zero{ZeroInit, a}; CORRADE_COMPARE(zero, expectedZero); CORRADE_COMPARE((Matrix4{ZeroInit, a}), expectedZero); }