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.
Since depth/stencil images can't be linear, I needed buffer/image copies
to test those, and conversely to test buffer/image copies I needed image
clears.
A pretty big chunk of work, and it led to a discovery of a SwiftShader
bug, which I will work around next. First Vulkan driver workaround, so
the whole scaffolding needs to get added as well.
There was a nasty issue when moving the Device -- because the Queue
instances are populated with the Device pointer in the constructor,
moving the Device makes the Queue device pointer invalid and those
instances are useless. Discovered this when using VulkanTester to test
an upcoming Queue::submit() -- until then, the Device pointer in the
Queue wasn't really used for anything and so this wasn't known.
Making the Device immovable is thus the only sane way to keep the
current Queue retrieval workflow, which I'd say is much cleaner than
having to manually query the device for queues later using some
error-prone indices and whatnot. On the other hand, this finally makes
it possible to have a failable device creation, instead of the device
creation failing on an assert (or failing silently when
CORRADE_NO_ASSERT is defined). This is consistent with how the GL
wrapper works.
Also, because all device-dependent objects need to keep a pointer to the
originating Device in order to access Vulkan function pointers, having
it immovable makes it considerably faster. I'll make Instance immovable
with tryCreate() next because it seems like a good thing to do there as
well.
Because the drivers don't seem to check that features are actually
supported for anything beyond VkPhysicalDeviceFeatures2, we have to do
that instead. Additionally, we also check if a feature is enabled but
the extension that needs it is not (which isn't checked by drivers
either).
This was way more pain that initially expected, especially in regards to
preserving externally-specified pNext chains without writing to them in
any way.
After I implemented the render pass wrapper, seeing how the
RenderPassCreateInfo structure and its dependencies were HUGE compared
to the actual tiny and lean RenderPass, I felt uneasy dragging their
definition along to every place where a RenderPass gets used. It's not
as bad with the others, but as new extensions are implemented I expect
that to get the same.
This change makes it easier for me to accept that Image.h / Buffer.h
depends on Memory.h. There isn't a real measurable difference when
building Magnum itself (50 ms out of 7 seconds for the Vk library
alone), but that's because most of the code (and tests) needs the
CreateInfo structures anyway.
More convenient to use since one doesn't have to explicitly store a
DeviceProperties instance to call pickQueueFamily() on it and then move
it to DeviceCreateInfo to keep it efficient.
This required a slight redesign of how DeviceProperties are stored in
DeviceCreateInfo, now we need the instance to be always valid (but it
can get never used). The wrap() API isn't doing any extra work so this
won't add any inefficiency.
Today I spent six hours wrongly convincing myself that it's a driver bug
when vkGetPhysicalDeviceProperties2() is null on a 1.1 instance for a
1.0 physical device. It's not a bug, it's me not reading specs
carefully.
This commit thus basically moves all Instance-level extension-dependent
state to DeviceProperties, because it's actually device-dependent. Which
makes the DeviceProperties class quite heavy and thus it's good it was
readied to be transferred all the way to a Device instance a few commits
back -- I don't really want to do all the dispatch, string processing,
sorting and other mess more times than strictly necessary.
In addition, DeviceProperties::apiVersion() got renamed to version() and
a new isVersionSupported() API got added, mirroring what's on Device
itself; plus thanks to the chicken-and-egg problem of having to call
vkGetPhysicalDeviceProperties() twice, the device version and other
things can now be retrieved in a slightly more efficient way.
Similarly to Corrade Assert.h, so it's possible to include this header
without having to worry about irrelevant overhead when asserts are
disabled.
Also test it properly, as it should have been from the start.
I have more and more cases where I need to query device properties later
down the road (memory capabilities, device name, ...) and leaving all
this up to the user / making this impossible to do in the library
internals is complicating everything too much.
Since there's a shitton of device properties with a new bag of props
coming with every other new extension, I expect the queries to get quite
involved / complicated over time (chaining 100s structs and such), so
let's design this upfront in a way that can avoid reqpeatedly querying
the same thing just because we needlessly discarded a fully populated
instance before.
It also means the users don't need to drag their own DeviceProperties
instance along anymore and can just let the Device take care of that.
Unfortunately the only nice way to make this work with DeviceCreateInfo
method chaining is to add & and && overloads for each. But it's quite
easy to test that all of them work and properly return a r-value
reference so it shouldn't be too much of a maintenance nightmare.