The whole class was a bad idea, why create something that's 99% similar
to another application and has just one platform-specific workaround? Of
course it resulted in this code being completely untested and not even
built anywhere, because it served a tiny insignificant use case.
To avoid losing all the code, I did my best in attempting to merge this
into the WindowlessEglApplication. But since, again, EGL isn't
really used on any Windows platform, I can't even say it builds
properly. Maybe not even the original code built.
It was quite a pile, and all of it was written just once, relying only
on hopefully-available model files that would hopefully touch most code
paths. Which means, extremely annoying to make changes in.
I extracted the code to a header that can be tested with a mocked-up
importer and without having to execute the utility itself, deduplicated
the image info printing code, fixed various inconsistencies (such as
data/field flags sometimes denoted with superfluous "flags:" and
sometimes not) and TODOs (such as 2D/3D skins, where there was no format
whatsoever that would have 2D skin support, so the code couldn't get
written).
Now it's finally possible to easily add the remaining missing features,
such as printing camera info.
Initially, if possible, by extracting the code into separate files and
testing those, instead of having to execute a binary and deal with
output redirection and other crazy things. The option propagation is
already extracted, so do that first.
Consistently with checkLink(), this avoids having to explicitly include
both Iterable and Reference in shader code. Alsod allowing people to
have direct arrays of shaders, runtime-sized lists of shaders etc.
A compat include is provided on a deprecated build to avoid breaking
existing code.
The class is rather heavy (strings, STL vector) and it'll stay heavier
than strictly needed even after the planned STL cleanup -- shader users
should not bear the overhead of Array, StringView etc. that it needs in
order to compile the shader sources.
I might eventually come to a different conclusion (maybe separating
GL::Shader population and usage like doing in Vulkan with CreateInfos),
but right now this commit has the best available solution -- converting
the instance to a lightweight class containing just ID and type, and
then converting that back to a GL::Shader upon checking compilation/link
status.
While at it, also removed the not-strictly-needed Optional usage from
the header. It wouldn't work with forward-declared GL::Shader anyway.
The whole time I thought this class doesn't need such APIs due to being
rather short-lived. But now with async shader compilation it's no longer
so short-lived.
There's no reason for those to exist anymore -- origiinally they were
added in a hopeful attempt to make use of parallel shader compilation,
but in practice that meant compiling at most two or three shaders at
once and still stalling until that was done, so not that great at all.
The new APIs provide much better opportunities for parallelism.
Fun fact:
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile() && frag.compile());
is actually one character shorter than
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
so not even typing convenience would be a reason to keep these.
The new async APIs were just checking the link status, and printing the
linker error. Because drivers commonly do all that in a single step,
without really separating compilation from linking (or at least that's
what I thought?), I assumed the linker error would contain *also* the
compilation error, if any.
But on a quick check with Mesa that's not the case, I only get "error:
linking with uncompiled/unspecialized shader", which is very useless.
Which means, to get proper error output, the checkLink() function now
explicitly takes a list of the input shaders. It will unconditionally go
through them at the beginning and call checkCompile() on each.
To further encourage the shaders to be passed, there's no default
argument -- so if the application calls checkCompile() on its own for
some reason, it has to pass an empty list to checkLink().
Until now it relied on the driver adding a \n after each message. Which
happened in 99% cases, but sometimes not, and it is really annoying in
that case. Right now I witnessed Mesa giving me a non-newlined message
if I call checkLink() and a shader compilation failed before, resulting
in nasty output like
error: linking with uncompiled/unspecialized shaderAssertion checkLink() failed at /home/mosra/Code/magnum/src/Magnum/Shaders/FlatGL.cpp:248
And I bet I encountered other weird cases, like there being two
newlines, or the message being just a newline without any other content,
thus spamming the output on every compilation. It's not practical to try
to find driver-specific workarounds here, so I'm just trimming always
and then rely on Debug adding its own newline after.
In particular:
- listing the *very important* stuff -- such as what macro to define to
make the library usable at all -- in the header
- mentioning what to do if cross-SO/DLL visibility is desired
The actual generated single-header file will be updated once I find more
time. Not now.
Marking it as having "some" caveats right now, will change it to none
once the remaining features like camera & light export are added and
once the mesh buffer views get more compact.
This happened because I made an early implementation of the batch
AbstractSceneConverter APIs, stashed it away, then implemented image
flags and then continued working on the stash, unaware that it's
outdated.
It makes no difference in this case, the State struct is not exported
even without the attribute. OTOH, it would need to have an EXPORT
attribute if it was desired to be exported, for example like done with
nested classes in GL::Framebuffer.