This was the original intention, but it didn't happen because of a bug:
what we need to know at this point is whether the push descriptor set is
being used in general (which is tracked by the corresponding Vulkan
extension bit), not whether the descriptors we're currently processing
are to be put in the push descriptor set (which is tracked by
`push_descriptor'). Indeed, `push_descriptor' is always false when
processing static samplers, precisely because we want to segregate them
in different sets.
This fixes a rendering bug in "The Dark Pictures Anthology: Man of
Medan".
Fixes: 07b7975d09
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58589
VK_DYNAMIC_STATE_VIEWPORT and VK_DYNAMIC_STATE_SCISSOR specify that
viewports and scissor rectangles are dynamic state, but not their
counts.
It took a while to notice this issue because the existing code seemed to
largely work as intended on hardware implementations, but tests using
the additional viewports would fail on llvmpipe.
Vulkan does support rendering without a fragment shader, and this seems
to work fine on current drivers. This commit gets rid of the last
embedded shader binary in libvkd3d, and may have a slight performance
advantage on hardware/drivers able to take advantage of the absence of a
fragment shader.
Since 4a94bfc2f6 we segregate
different D3D12 descriptor types in different Vulkan descriptor sets.
This change was introduced to reduce descriptor wasting when
allocating a new descriptor pool; that can be very useful when
using virtual heaps, which have to often cycle through many
descriptors, but it is expected to have limited impact for Vulkan
heaps, given that in that case most descriptors are allocated through
the descriptor heap rather than through the command allocator.
Instead, it has a rather detrimental effect with Vulkan heaps,
because it tends to use many more Vulkan descriptor sets than
necessary, often with just a handful of descriptors each. This
causes a regression on some Vulkan implementations that support
too few descriptor sets.
With this change we revert to a situation similar to before,
stuffing all the descriptors that do not live in a root
descriptor table in as few descriptor sets as possible (at most
one or two, depending on whether push descriptors are used).
Otherwise ubsan reports runtime errors such as:
libs/vkd3d-shader/ir.c:4731:5: runtime error: null pointer passed as argument 1, which is declared to never be null
Creating a pool of 16k descriptors is wasteful if an allocator only uses
a fraction of them, so start at 1k and double for each subsequent
allocation until 16k is reached.
Now that our Vulkan descriptor sets contain only a single vkd3d
descriptor type, we're able to create descriptor pools containing only a
single vkd3d descriptor type as well. This avoids wasting unallocated
descriptors of one type when we run out of descriptors of another type.
We currently create statically sized descriptor pools, shared among
different descriptor types. Once we're unable to allocate a descriptor
set from a pool, we create a new pool. The unfortunate but predictable
consequence is that when we run out of descriptors of one type, we waste
any unallocated descriptors of the other types.
Dynamically adjusting the pool sizes could mitigate the issue, but it
seems non-trivial to handle all the edge cases, particularly in
situations where the descriptor count ratios change significantly
between frames. Instead, by storing only a single vkd3d descriptor type
in each Vulkan descriptor set we're able to create separate descriptor
pools for each vkd3d descriptor type, which also avoids the issue.
The main drawback of using separate descriptor sets for each descriptor
type is that we can no longer pack all bounded descriptor ranges into a
single descriptor set, potentially leaving fewer descriptor sets
available for unbounded ranges. That seems worth it, but we may end up
having to switch to a more complicated strategy if this ends up being a
problem on Vulkan implementations with a very limited number of
available descriptor sets.
Currently the mutable descriptor set is repeated many times in the
pipeline layout in order to cover the indices for all the
descriptor types that would be present if mutable descriptors were
not used. This is useless and wasteful, but was necessary before
the descriptor sets backing the SRV-UAV-CBV heap were moved at the
end of the allocation table because descriptor set indices are
currently a compile-time constant in many places.
Now this is not needed any more and we can just avoid putting
many copies of the mutable descriptor set in the pipeline layout,
making it easier to meet Vulkan implementation limits.
So we avoid hardcoding that it is number zero. There are two
goals here: first making the code easier to understand and
second allow reshuffling the descriptor set allocation in a
later commit.
Slightly simplifies descriptor write addressing, and makes layouts
essentially the same as array layouts, differing only in the binding
details, and therefore easier to understand. This also simplifies the
addition of storage buffer bindings, which can all be added onto the end.