Reduce the amount of descriptor pool allocations on Vulkan (#5673)
* Reduce the amount of descriptor pool allocations on Vulkan * Formatting * Slice can be simplified * Make GetDescriptorPoolSizes static * Adjust CanFit calculation so that TryAllocateDescriptorSets never fails * Remove unused field
This commit is contained in:
parent
4a835bb2b9
commit
4744bde0e5
6 changed files with 173 additions and 57 deletions
|
@ -27,6 +27,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
public bool InUse;
|
public bool InUse;
|
||||||
public bool InConsumption;
|
public bool InConsumption;
|
||||||
|
public int SubmissionCount;
|
||||||
public CommandBuffer CommandBuffer;
|
public CommandBuffer CommandBuffer;
|
||||||
public FenceHolder Fence;
|
public FenceHolder Fence;
|
||||||
public SemaphoreHolder Semaphore;
|
public SemaphoreHolder Semaphore;
|
||||||
|
@ -193,6 +194,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return _commandBuffers[cbIndex].Fence;
|
return _commandBuffers[cbIndex].Fence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetSubmissionCount(int cbIndex)
|
||||||
|
{
|
||||||
|
return _commandBuffers[cbIndex].SubmissionCount;
|
||||||
|
}
|
||||||
|
|
||||||
private int FreeConsumed(bool wait)
|
private int FreeConsumed(bool wait)
|
||||||
{
|
{
|
||||||
int freeEntry = 0;
|
int freeEntry = 0;
|
||||||
|
@ -282,6 +288,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
Debug.Assert(entry.CommandBuffer.Handle == cbs.CommandBuffer.Handle);
|
Debug.Assert(entry.CommandBuffer.Handle == cbs.CommandBuffer.Handle);
|
||||||
entry.InUse = false;
|
entry.InUse = false;
|
||||||
entry.InConsumption = true;
|
entry.InConsumption = true;
|
||||||
|
entry.SubmissionCount++;
|
||||||
_inUseCount--;
|
_inUseCount--;
|
||||||
|
|
||||||
var commandBuffer = entry.CommandBuffer;
|
var commandBuffer = entry.CommandBuffer;
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
class DescriptorSetManager : IDisposable
|
class DescriptorSetManager : IDisposable
|
||||||
{
|
{
|
||||||
private const uint DescriptorPoolMultiplier = 16;
|
public const uint MaxSets = 16;
|
||||||
|
|
||||||
public class DescriptorPoolHolder : IDisposable
|
public class DescriptorPoolHolder : IDisposable
|
||||||
{
|
{
|
||||||
|
@ -14,36 +14,28 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
public Device Device { get; }
|
public Device Device { get; }
|
||||||
|
|
||||||
private readonly DescriptorPool _pool;
|
private readonly DescriptorPool _pool;
|
||||||
private readonly uint _capacity;
|
private int _freeDescriptors;
|
||||||
private int _totalSets;
|
private int _totalSets;
|
||||||
private int _setsInUse;
|
private int _setsInUse;
|
||||||
private bool _done;
|
private bool _done;
|
||||||
|
|
||||||
public unsafe DescriptorPoolHolder(Vk api, Device device)
|
public unsafe DescriptorPoolHolder(Vk api, Device device, ReadOnlySpan<DescriptorPoolSize> poolSizes, bool updateAfterBind)
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
Device = device;
|
Device = device;
|
||||||
|
|
||||||
var poolSizes = new[]
|
foreach (var poolSize in poolSizes)
|
||||||
{
|
{
|
||||||
new DescriptorPoolSize(DescriptorType.UniformBuffer, (1 + Constants.MaxUniformBufferBindings) * DescriptorPoolMultiplier),
|
_freeDescriptors += (int)poolSize.DescriptorCount;
|
||||||
new DescriptorPoolSize(DescriptorType.StorageBuffer, Constants.MaxStorageBufferBindings * DescriptorPoolMultiplier),
|
}
|
||||||
new DescriptorPoolSize(DescriptorType.CombinedImageSampler, Constants.MaxTextureBindings * DescriptorPoolMultiplier),
|
|
||||||
new DescriptorPoolSize(DescriptorType.StorageImage, Constants.MaxImageBindings * DescriptorPoolMultiplier),
|
|
||||||
new DescriptorPoolSize(DescriptorType.UniformTexelBuffer, Constants.MaxTextureBindings * DescriptorPoolMultiplier),
|
|
||||||
new DescriptorPoolSize(DescriptorType.StorageTexelBuffer, Constants.MaxImageBindings * DescriptorPoolMultiplier),
|
|
||||||
};
|
|
||||||
|
|
||||||
uint maxSets = (uint)poolSizes.Length * DescriptorPoolMultiplier;
|
|
||||||
|
|
||||||
_capacity = maxSets;
|
|
||||||
|
|
||||||
fixed (DescriptorPoolSize* pPoolsSize = poolSizes)
|
fixed (DescriptorPoolSize* pPoolsSize = poolSizes)
|
||||||
{
|
{
|
||||||
var descriptorPoolCreateInfo = new DescriptorPoolCreateInfo
|
var descriptorPoolCreateInfo = new DescriptorPoolCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.DescriptorPoolCreateInfo,
|
SType = StructureType.DescriptorPoolCreateInfo,
|
||||||
MaxSets = maxSets,
|
Flags = updateAfterBind ? DescriptorPoolCreateFlags.UpdateAfterBindBit : DescriptorPoolCreateFlags.None,
|
||||||
|
MaxSets = MaxSets,
|
||||||
PoolSizeCount = (uint)poolSizes.Length,
|
PoolSizeCount = (uint)poolSizes.Length,
|
||||||
PPoolSizes = pPoolsSize,
|
PPoolSizes = pPoolsSize,
|
||||||
};
|
};
|
||||||
|
@ -52,18 +44,22 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DescriptorSetCollection AllocateDescriptorSets(ReadOnlySpan<DescriptorSetLayout> layouts)
|
public unsafe DescriptorSetCollection AllocateDescriptorSets(ReadOnlySpan<DescriptorSetLayout> layouts, int consumedDescriptors)
|
||||||
{
|
{
|
||||||
TryAllocateDescriptorSets(layouts, isTry: false, out var dsc);
|
TryAllocateDescriptorSets(layouts, consumedDescriptors, isTry: false, out var dsc);
|
||||||
return dsc;
|
return dsc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryAllocateDescriptorSets(ReadOnlySpan<DescriptorSetLayout> layouts, out DescriptorSetCollection dsc)
|
public bool TryAllocateDescriptorSets(ReadOnlySpan<DescriptorSetLayout> layouts, int consumedDescriptors, out DescriptorSetCollection dsc)
|
||||||
{
|
{
|
||||||
return TryAllocateDescriptorSets(layouts, isTry: true, out dsc);
|
return TryAllocateDescriptorSets(layouts, consumedDescriptors, isTry: true, out dsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe bool TryAllocateDescriptorSets(ReadOnlySpan<DescriptorSetLayout> layouts, bool isTry, out DescriptorSetCollection dsc)
|
private unsafe bool TryAllocateDescriptorSets(
|
||||||
|
ReadOnlySpan<DescriptorSetLayout> layouts,
|
||||||
|
int consumedDescriptors,
|
||||||
|
bool isTry,
|
||||||
|
out DescriptorSetCollection dsc)
|
||||||
{
|
{
|
||||||
Debug.Assert(!_done);
|
Debug.Assert(!_done);
|
||||||
|
|
||||||
|
@ -84,7 +80,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
var result = Api.AllocateDescriptorSets(Device, &descriptorSetAllocateInfo, pDescriptorSets);
|
var result = Api.AllocateDescriptorSets(Device, &descriptorSetAllocateInfo, pDescriptorSets);
|
||||||
if (isTry && result == Result.ErrorOutOfPoolMemory)
|
if (isTry && result == Result.ErrorOutOfPoolMemory)
|
||||||
{
|
{
|
||||||
_totalSets = (int)_capacity;
|
_totalSets = (int)MaxSets;
|
||||||
_done = true;
|
_done = true;
|
||||||
DestroyIfDone();
|
DestroyIfDone();
|
||||||
dsc = default;
|
dsc = default;
|
||||||
|
@ -95,6 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_freeDescriptors -= consumedDescriptors;
|
||||||
_totalSets += layouts.Length;
|
_totalSets += layouts.Length;
|
||||||
_setsInUse += layouts.Length;
|
_setsInUse += layouts.Length;
|
||||||
|
|
||||||
|
@ -109,9 +106,15 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
DestroyIfDone();
|
DestroyIfDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanFit(int count)
|
public bool CanFit(int setsCount, int descriptorsCount)
|
||||||
{
|
{
|
||||||
if (_totalSets + count <= _capacity)
|
// Try to determine if an allocation with the given parameters will succeed.
|
||||||
|
// An allocation may fail if the sets count or descriptors count exceeds the available counts
|
||||||
|
// of the pool.
|
||||||
|
// Not getting that right is not fatal, it will just create a new pool and try again,
|
||||||
|
// but it is less efficient.
|
||||||
|
|
||||||
|
if (_totalSets + setsCount <= MaxSets && _freeDescriptors >= descriptorsCount)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -148,46 +151,74 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Device _device;
|
private readonly Device _device;
|
||||||
private DescriptorPoolHolder _currentPool;
|
private readonly DescriptorPoolHolder[] _currentPools;
|
||||||
|
|
||||||
public DescriptorSetManager(Device device)
|
public DescriptorSetManager(Device device, int poolCount)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
|
_currentPools = new DescriptorPoolHolder[poolCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
public Auto<DescriptorSetCollection> AllocateDescriptorSet(Vk api, DescriptorSetLayout layout)
|
public Auto<DescriptorSetCollection> AllocateDescriptorSet(
|
||||||
|
Vk api,
|
||||||
|
DescriptorSetLayout layout,
|
||||||
|
ReadOnlySpan<DescriptorPoolSize> poolSizes,
|
||||||
|
int poolIndex,
|
||||||
|
int consumedDescriptors,
|
||||||
|
bool updateAfterBind)
|
||||||
{
|
{
|
||||||
Span<DescriptorSetLayout> layouts = stackalloc DescriptorSetLayout[1];
|
Span<DescriptorSetLayout> layouts = stackalloc DescriptorSetLayout[1];
|
||||||
layouts[0] = layout;
|
layouts[0] = layout;
|
||||||
return AllocateDescriptorSets(api, layouts);
|
return AllocateDescriptorSets(api, layouts, poolSizes, poolIndex, consumedDescriptors, updateAfterBind);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Auto<DescriptorSetCollection> AllocateDescriptorSets(Vk api, ReadOnlySpan<DescriptorSetLayout> layouts)
|
public Auto<DescriptorSetCollection> AllocateDescriptorSets(
|
||||||
|
Vk api,
|
||||||
|
ReadOnlySpan<DescriptorSetLayout> layouts,
|
||||||
|
ReadOnlySpan<DescriptorPoolSize> poolSizes,
|
||||||
|
int poolIndex,
|
||||||
|
int consumedDescriptors,
|
||||||
|
bool updateAfterBind)
|
||||||
{
|
{
|
||||||
// If we fail the first time, just create a new pool and try again.
|
// If we fail the first time, just create a new pool and try again.
|
||||||
if (!GetPool(api, layouts.Length).TryAllocateDescriptorSets(layouts, out var dsc))
|
|
||||||
|
var pool = GetPool(api, poolSizes, poolIndex, layouts.Length, consumedDescriptors, updateAfterBind);
|
||||||
|
if (!pool.TryAllocateDescriptorSets(layouts, consumedDescriptors, out var dsc))
|
||||||
{
|
{
|
||||||
dsc = GetPool(api, layouts.Length).AllocateDescriptorSets(layouts);
|
pool = GetPool(api, poolSizes, poolIndex, layouts.Length, consumedDescriptors, updateAfterBind);
|
||||||
|
dsc = pool.AllocateDescriptorSets(layouts, consumedDescriptors);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Auto<DescriptorSetCollection>(dsc);
|
return new Auto<DescriptorSetCollection>(dsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DescriptorPoolHolder GetPool(Vk api, int requiredCount)
|
private DescriptorPoolHolder GetPool(
|
||||||
|
Vk api,
|
||||||
|
ReadOnlySpan<DescriptorPoolSize> poolSizes,
|
||||||
|
int poolIndex,
|
||||||
|
int setsCount,
|
||||||
|
int descriptorsCount,
|
||||||
|
bool updateAfterBind)
|
||||||
{
|
{
|
||||||
if (_currentPool == null || !_currentPool.CanFit(requiredCount))
|
ref DescriptorPoolHolder currentPool = ref _currentPools[poolIndex];
|
||||||
|
|
||||||
|
if (currentPool == null || !currentPool.CanFit(setsCount, descriptorsCount))
|
||||||
{
|
{
|
||||||
_currentPool = new DescriptorPoolHolder(api, _device);
|
currentPool = new DescriptorPoolHolder(api, _device, poolSizes, updateAfterBind);
|
||||||
}
|
}
|
||||||
|
|
||||||
return _currentPool;
|
return currentPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
_currentPool?.Dispose();
|
for (int index = 0; index < _currentPools.Length; index++)
|
||||||
|
{
|
||||||
|
_currentPools[index]?.Dispose();
|
||||||
|
_currentPools[index] = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
private BitMapStruct<Array2<long>> _uniformMirrored;
|
private BitMapStruct<Array2<long>> _uniformMirrored;
|
||||||
private BitMapStruct<Array2<long>> _storageMirrored;
|
private BitMapStruct<Array2<long>> _storageMirrored;
|
||||||
|
|
||||||
|
private bool _updateDescriptorCacheCbIndex;
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
private enum DirtyFlags
|
private enum DirtyFlags
|
||||||
{
|
{
|
||||||
|
@ -218,6 +220,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
public void SetProgram(ShaderCollection program)
|
public void SetProgram(ShaderCollection program)
|
||||||
{
|
{
|
||||||
_program = program;
|
_program = program;
|
||||||
|
_updateDescriptorCacheCbIndex = true;
|
||||||
_dirty = DirtyFlags.All;
|
_dirty = DirtyFlags.All;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +493,13 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
var dummyBuffer = _dummyBuffer?.GetBuffer();
|
var dummyBuffer = _dummyBuffer?.GetBuffer();
|
||||||
|
|
||||||
var dsc = program.GetNewDescriptorSetCollection(_gd, cbs.CommandBufferIndex, setIndex, out var isNew).Get(cbs);
|
if (_updateDescriptorCacheCbIndex)
|
||||||
|
{
|
||||||
|
_updateDescriptorCacheCbIndex = false;
|
||||||
|
program.UpdateDescriptorCacheCommandBufferIndex(cbs.CommandBufferIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dsc = program.GetNewDescriptorSetCollection(setIndex, out var isNew).Get(cbs);
|
||||||
|
|
||||||
if (!program.HasMinimalLayout)
|
if (!program.HasMinimalLayout)
|
||||||
{
|
{
|
||||||
|
@ -697,6 +706,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
public void SignalCommandBufferChange()
|
public void SignalCommandBufferChange()
|
||||||
{
|
{
|
||||||
|
_updateDescriptorCacheCbIndex = true;
|
||||||
_dirty = DirtyFlags.All;
|
_dirty = DirtyFlags.All;
|
||||||
|
|
||||||
_uniformSet.Clear();
|
_uniformSet.Clear();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
@ -7,15 +8,28 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
class PipelineLayoutCacheEntry
|
class PipelineLayoutCacheEntry
|
||||||
{
|
{
|
||||||
|
// Those were adjusted based on current descriptor usage and the descriptor counts usually used on pipeline layouts.
|
||||||
|
// It might be a good idea to tweak them again if those change, or maybe find a way to calculate an optimal value dynamically.
|
||||||
|
private const uint DefaultUniformBufferPoolCapacity = 19 * DescriptorSetManager.MaxSets;
|
||||||
|
private const uint DefaultStorageBufferPoolCapacity = 16 * DescriptorSetManager.MaxSets;
|
||||||
|
private const uint DefaultTexturePoolCapacity = 128 * DescriptorSetManager.MaxSets;
|
||||||
|
private const uint DefaultImagePoolCapacity = 8 * DescriptorSetManager.MaxSets;
|
||||||
|
|
||||||
|
private const int MaxPoolSizesPerSet = 2;
|
||||||
|
|
||||||
private readonly VulkanRenderer _gd;
|
private readonly VulkanRenderer _gd;
|
||||||
private readonly Device _device;
|
private readonly Device _device;
|
||||||
|
|
||||||
public DescriptorSetLayout[] DescriptorSetLayouts { get; }
|
public DescriptorSetLayout[] DescriptorSetLayouts { get; }
|
||||||
public PipelineLayout PipelineLayout { get; }
|
public PipelineLayout PipelineLayout { get; }
|
||||||
|
|
||||||
|
private readonly int[] _consumedDescriptorsPerSet;
|
||||||
|
|
||||||
private readonly List<Auto<DescriptorSetCollection>>[][] _dsCache;
|
private readonly List<Auto<DescriptorSetCollection>>[][] _dsCache;
|
||||||
|
private List<Auto<DescriptorSetCollection>>[] _currentDsCache;
|
||||||
private readonly int[] _dsCacheCursor;
|
private readonly int[] _dsCacheCursor;
|
||||||
private int _dsLastCbIndex;
|
private int _dsLastCbIndex;
|
||||||
|
private int _dsLastSubmissionCount;
|
||||||
|
|
||||||
private PipelineLayoutCacheEntry(VulkanRenderer gd, Device device, int setsCount)
|
private PipelineLayoutCacheEntry(VulkanRenderer gd, Device device, int setsCount)
|
||||||
{
|
{
|
||||||
|
@ -44,29 +58,55 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
bool usePushDescriptors) : this(gd, device, setDescriptors.Count)
|
bool usePushDescriptors) : this(gd, device, setDescriptors.Count)
|
||||||
{
|
{
|
||||||
(DescriptorSetLayouts, PipelineLayout) = PipelineLayoutFactory.Create(gd, device, setDescriptors, usePushDescriptors);
|
(DescriptorSetLayouts, PipelineLayout) = PipelineLayoutFactory.Create(gd, device, setDescriptors, usePushDescriptors);
|
||||||
|
|
||||||
|
_consumedDescriptorsPerSet = new int[setDescriptors.Count];
|
||||||
|
|
||||||
|
for (int setIndex = 0; setIndex < setDescriptors.Count; setIndex++)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
foreach (var descriptor in setDescriptors[setIndex].Descriptors)
|
||||||
|
{
|
||||||
|
count += descriptor.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Auto<DescriptorSetCollection> GetNewDescriptorSetCollection(
|
_consumedDescriptorsPerSet[setIndex] = count;
|
||||||
VulkanRenderer gd,
|
}
|
||||||
int commandBufferIndex,
|
}
|
||||||
int setIndex,
|
|
||||||
out bool isNew)
|
public void UpdateCommandBufferIndex(int commandBufferIndex)
|
||||||
{
|
{
|
||||||
if (_dsLastCbIndex != commandBufferIndex)
|
int submissionCount = _gd.CommandBufferPool.GetSubmissionCount(commandBufferIndex);
|
||||||
|
|
||||||
|
if (_dsLastCbIndex != commandBufferIndex || _dsLastSubmissionCount != submissionCount)
|
||||||
{
|
{
|
||||||
_dsLastCbIndex = commandBufferIndex;
|
_dsLastCbIndex = commandBufferIndex;
|
||||||
|
_dsLastSubmissionCount = submissionCount;
|
||||||
|
Array.Clear(_dsCacheCursor);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _dsCacheCursor.Length; i++)
|
_currentDsCache = _dsCache[commandBufferIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DescriptorSetCollection> GetNewDescriptorSetCollection(int setIndex, out bool isNew)
|
||||||
{
|
{
|
||||||
_dsCacheCursor[i] = 0;
|
var list = _currentDsCache[setIndex];
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var list = _dsCache[commandBufferIndex][setIndex];
|
|
||||||
int index = _dsCacheCursor[setIndex]++;
|
int index = _dsCacheCursor[setIndex]++;
|
||||||
if (index == list.Count)
|
if (index == list.Count)
|
||||||
{
|
{
|
||||||
var dsc = gd.DescriptorSetManager.AllocateDescriptorSet(gd.Api, DescriptorSetLayouts[setIndex]);
|
Span<DescriptorPoolSize> poolSizes = stackalloc DescriptorPoolSize[MaxPoolSizesPerSet];
|
||||||
|
poolSizes = GetDescriptorPoolSizes(poolSizes, setIndex);
|
||||||
|
|
||||||
|
int consumedDescriptors = _consumedDescriptorsPerSet[setIndex];
|
||||||
|
|
||||||
|
var dsc = _gd.DescriptorSetManager.AllocateDescriptorSet(
|
||||||
|
_gd.Api,
|
||||||
|
DescriptorSetLayouts[setIndex],
|
||||||
|
poolSizes,
|
||||||
|
setIndex,
|
||||||
|
consumedDescriptors,
|
||||||
|
false);
|
||||||
|
|
||||||
list.Add(dsc);
|
list.Add(dsc);
|
||||||
isNew = true;
|
isNew = true;
|
||||||
return dsc;
|
return dsc;
|
||||||
|
@ -76,6 +116,33 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return list[index];
|
return list[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Span<DescriptorPoolSize> GetDescriptorPoolSizes(Span<DescriptorPoolSize> output, int setIndex)
|
||||||
|
{
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
switch (setIndex)
|
||||||
|
{
|
||||||
|
case PipelineBase.UniformSetIndex:
|
||||||
|
output[0] = new(DescriptorType.UniformBuffer, DefaultUniformBufferPoolCapacity);
|
||||||
|
break;
|
||||||
|
case PipelineBase.StorageSetIndex:
|
||||||
|
output[0] = new(DescriptorType.StorageBuffer, DefaultStorageBufferPoolCapacity);
|
||||||
|
break;
|
||||||
|
case PipelineBase.TextureSetIndex:
|
||||||
|
output[0] = new(DescriptorType.CombinedImageSampler, DefaultTexturePoolCapacity);
|
||||||
|
output[1] = new(DescriptorType.UniformTexelBuffer, DefaultTexturePoolCapacity);
|
||||||
|
count = 2;
|
||||||
|
break;
|
||||||
|
case PipelineBase.ImageSetIndex:
|
||||||
|
output[0] = new(DescriptorType.StorageImage, DefaultImagePoolCapacity);
|
||||||
|
output[1] = new(DescriptorType.StorageTexelBuffer, DefaultImagePoolCapacity);
|
||||||
|
count = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output[..count];
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual unsafe void Dispose(bool disposing)
|
protected virtual unsafe void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
|
|
@ -464,13 +464,14 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Auto<DescriptorSetCollection> GetNewDescriptorSetCollection(
|
public void UpdateDescriptorCacheCommandBufferIndex(int commandBufferIndex)
|
||||||
VulkanRenderer gd,
|
|
||||||
int commandBufferIndex,
|
|
||||||
int setIndex,
|
|
||||||
out bool isNew)
|
|
||||||
{
|
{
|
||||||
return _plce.GetNewDescriptorSetCollection(gd, commandBufferIndex, setIndex, out isNew);
|
_plce.UpdateCommandBufferIndex(commandBufferIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Auto<DescriptorSetCollection> GetNewDescriptorSetCollection(int setIndex, out bool isNew)
|
||||||
|
{
|
||||||
|
return _plce.GetNewDescriptorSetCollection(setIndex, out isNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
|
@ -347,7 +347,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex);
|
CommandBufferPool = new CommandBufferPool(Api, _device, Queue, QueueLock, queueFamilyIndex);
|
||||||
|
|
||||||
DescriptorSetManager = new DescriptorSetManager(_device);
|
DescriptorSetManager = new DescriptorSetManager(_device, PipelineBase.DescriptorSetLayouts);
|
||||||
|
|
||||||
PipelineLayoutCache = new PipelineLayoutCache();
|
PipelineLayoutCache = new PipelineLayoutCache();
|
||||||
|
|
||||||
|
|
Reference in a new issue