This "type erased std::vector member" was done in the times before
growable arrays were a thing, and kind of made sense to go the extra way
to avoid a <vector> include in the header. Except that it made rather
unportable assumptions about std::vector size, which weren't correct for
example with _GLIBXX_ASSERTIONS set.
But what was *completely* unacceptable was that the vector was of one or
another type depending on the GL feature set present in the current
context. Apart from adding a lot of extra *nasty* logic to construction,
moves and destruction, this approach led to the mesh instance asking the
current context on destruction in order to know whether a destructor
should be called on std::vector<Buffer> or std::vector<AttributeLayout>.
Ugh.
Now it's a regular Array member (which isn't *that* heavy to need such
type-erased treatment, although it eventually could be), and thanks to
the AttributeLayout packing improvements in previous commits it's no
longer prohibitively wasteful to just abuse AttributeLayout instances to
store just owning Buffer instances alone -- doing so now wastes only 16
bytes per buffer, compared to 36 before. Given there's usually just one
or two vertex buffers per mesh (compared to attributes, which are
usually 4 or more), it should be fine.
The MeshGLTest::destructMovedOutInstance() test added few commits back
also no longer asserts on no GL context being present.
It was used just for certain corner cases that weren't covered by
{EXT,OES}_draw_elements_base_vertex already, but because of a wrongly
understood extension interaction the EXT/OES multidraw entrypoint (which
isn't implemented on ANGLE) was used from these as well.
And while trying to disable the two extensions for the MeshGLTest I
discovered the test half-expects the ANGLE variant to be implemented and
so I finished it for both the single-draw and multi-draw case.
The extension interaction that makes base-vertex multidraw calls broken
on ANGLE will be fixed in the following commit.
Yes, this is only ever provided by an ANGLE extension, and as you might
have guessed, The Great Google Overlords didn't bother caring to have
this supported outside of their browser.
Since the main point of the low-level API is to make use of the
EXT_multi_draw_arrays / ANGLE_multi_draw / WEBGL_multi_draw extensions
for a reduced driver overhead *and* the builtin gl_DrawID variable, it
just doesn't make sense to provide a fallback to draw() in a loop. When
the extensions are not available, the user has to do extra work in order
to supply proper UBO draw offset for each draw call, and thus the
fallback path has basically no practical use.
On the other hand, draw() taking the MeshView instances is kept as-is --
this one is rather old and so breaking compatibility would be an
unnecessary pain point. Plus, since it has to allocate the contiguous
arrays internally, it's not desirable for any fast-path rendering
anyway.
Because a MeshView might not be the best thing to have when you are
submitting a batch of thousand draws. It takes a strided array views to
allow for more flexibility, but can also detect if the input is already
contiguous and use it as-is.
UNFORTUNATELY the GL 1.0 legacy still continues to stink and so there
has to be a 64-bit-specific overload which is the *actual* variant that
doesn't allocate because glMultiDrawElements takes a `void**` for INDEX
OFFSETS and it's IN BYTES! Which foolish soul designed such a thing back
in the 1860s, I wonder. There's no reason to not have an index offset
in elements because all indices have to have the same type ANYWAY. And
yes, I wasted about three hours debugging driver crashes because I
THOUGHT this parameter takes offset in elements, not bytes.
Also note: on 32-bit platforms this depends on latest Corrade with the
CORRADE_TARGET_32BIT definition. Spent an embarrassing amount of time
wondering why all local builds but Emscripten work.
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!
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.
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 <string> and <vector> 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.
This is actually a preparation to make buffer-owning meshes a
possibility (where I would need an union of vectors otherwise),
nevertheless it removes the dependency on a vector.
Was Magnum::GL::Extensions::GL before and the redundancy was completely
unnecessary. Potential future extensions coming from GLX, EGL or whatnot
will most probably be in the Platform namespace in a completely separate
file, so this is not a problem.
All code internal to the GL library is affected, not much the outside,
as that is handled by the compatibility alias.
At the moment just the GL library itself w/o the tests, and without
backwards compatibility aliases. The following types were left in the
root namespace, despite being in the GL/ directory, as they will get
moved back soon:
* Image, CompressedImage and their dimensional typedefs
* ImageView, CompressedImageView and their dimensional typedefs
* PixelStorage
Not PixelFormat etc., that one will stay in the GL namespace and a
completely new PixelFormat enum will be provided in the root namespace.
Minimal updates (just the include guards) so Git is hopefully able to
detect the rename and track the history properly.
Everything except Magnum::GL doesn't compile now.
The original goal was to avoid branches when binding the vertex
attributes for drawing, so I stored float, integral and double
attributes in separate std::vector instances and then was going through
each one of them in separate loop. In retrospect that was _not_ a good
idea, because it results in larger Mesh class, two more allocations
resulting in far more pointer chasing and more complicated
constructor/destructor.
Now everything is stored in a single vector. I may optimize it further
by not calling the constructor/destructor on it when VAOs are used.
Actually properly supporting ANGLE_instanced_arrays. Emscripten
currently has the functions without the ANGLE suffix. Only causes linker
warnings when not used, need to fill a bugreport and fix properly.
This function was added to ARB_instanced_arrays spec very late and thus
some implementations don't provide it (one case being AMD drivers on
Linux). If that function is not available, the non-DSA VAO specification
is used instead.
In OpenGL ES this is implemented in EXT_multi_draw_arrays extension, if
it is not available, the functionality is emulated using sequence of
normal draw() calls.