Vulkan: Use push descriptors for uniform bindings when possible (#6154)

* Fix Push Descriptors

* Use push descriptor templates

* Use reserved bindings

* Formatting

* Disable when using MVK

("my heart will go on" starts playing as thousands of mac users shed a tear in unison)

* Introduce limit on push descriptor binding number

The bitmask used for updating push descriptors is ulong, so only 64 bindings can be tracked for now.

* Address feedback

* Fix logic for binding rejection

Should only offset limit when reserved bindings are less than the requested one.

* Workaround pascal and older nv bug

* Add GPU number detection for nvidia

* Only do workaround if it's valid to do so.
This commit is contained in:
riperiperi 2024-02-17 00:41:30 +00:00 committed by GitHub
parent e37735ed26
commit 4218311e6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 395 additions and 16 deletions

View file

@ -31,6 +31,11 @@ namespace Ryujinx.Graphics.Vulkan
private int _dsLastCbIndex;
private int _dsLastSubmissionCount;
private readonly Dictionary<long, DescriptorSetTemplate> _pdTemplates;
private readonly ResourceDescriptorCollection _pdDescriptors;
private long _lastPdUsage;
private DescriptorSetTemplate _lastPdTemplate;
private PipelineLayoutCacheEntry(VulkanRenderer gd, Device device, int setsCount)
{
_gd = gd;
@ -72,6 +77,12 @@ namespace Ryujinx.Graphics.Vulkan
_consumedDescriptorsPerSet[setIndex] = count;
}
if (usePushDescriptors)
{
_pdDescriptors = setDescriptors[0];
_pdTemplates = new();
}
}
public void UpdateCommandBufferIndex(int commandBufferIndex)
@ -143,10 +154,39 @@ namespace Ryujinx.Graphics.Vulkan
return output[..count];
}
public DescriptorSetTemplate GetPushDescriptorTemplate(PipelineBindPoint pbp, long updateMask)
{
if (_lastPdUsage == updateMask && _lastPdTemplate != null)
{
// Most likely result is that it asks to update the same buffers.
return _lastPdTemplate;
}
if (!_pdTemplates.TryGetValue(updateMask, out DescriptorSetTemplate template))
{
template = new DescriptorSetTemplate(_gd, _device, _pdDescriptors, updateMask, this, pbp, 0);
_pdTemplates.Add(updateMask, template);
}
_lastPdUsage = updateMask;
_lastPdTemplate = template;
return template;
}
protected virtual unsafe void Dispose(bool disposing)
{
if (disposing)
{
if (_pdTemplates != null)
{
foreach (DescriptorSetTemplate template in _pdTemplates.Values)
{
template.Dispose();
}
}
for (int i = 0; i < _dsCache.Length; i++)
{
for (int j = 0; j < _dsCache[i].Length; j++)