From cd3ad0a6ab06f57c29b849427619dcc6c652e849 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Fri, 17 Jun 2022 23:23:43 +0100 Subject: [PATCH] Push descriptor support check, buffer redundancy checks Should make push descriptors faster, needs more testing though. --- .../DescriptorSetUpdater.cs | 105 +++++++++++++++--- .../HardwareCapabilities.cs | 3 + Ryujinx.Graphics.Vulkan/ShaderCollection.cs | 2 +- .../VulkanGraphicsDevice.cs | 1 + 4 files changed, 92 insertions(+), 19 deletions(-) diff --git a/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs index e6a9bff4c..7fa8d9e29 100644 --- a/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs +++ b/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs @@ -30,6 +30,10 @@ namespace Ryujinx.Graphics.Vulkan private BufferView[] _bufferTextures; private BufferView[] _bufferImages; + private bool[] _uniformSet; + private bool[] _storageSet; + private Silk.NET.Vulkan.Buffer _cachedSupportBuffer; + [Flags] private enum DirtyFlags { @@ -68,6 +72,9 @@ namespace Ryujinx.Graphics.Vulkan _bufferTextures = new BufferView[Constants.MaxTextureBindings]; _bufferImages = new BufferView[Constants.MaxImageBindings]; + _uniformSet = new bool[Constants.MaxUniformBufferBindings]; + _storageSet = new bool[Constants.MaxStorageBufferBindings]; + if (gd.Capabilities.SupportsNullDescriptors) { // If null descriptors are supported, we can pass null as the handle. @@ -147,14 +154,25 @@ namespace Ryujinx.Graphics.Vulkan for (int i = 0; i < buffers.Length; i++) { var buffer = buffers[i]; + int index = first + i; - _storageBufferRefs[first + i] = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false); + Auto vkBuffer = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false); + ref Auto currentVkBuffer = ref _storageBufferRefs[index]; - _storageBuffers[first + i] = new DescriptorBufferInfo() + DescriptorBufferInfo info = new DescriptorBufferInfo() { Offset = (ulong)buffer.Offset, Range = (ulong)buffer.Size }; + ref DescriptorBufferInfo currentInfo = ref _storageBuffers[index]; + + if (vkBuffer != currentVkBuffer || currentInfo.Offset != info.Offset || currentInfo.Range != info.Range) + { + _storageSet[index] = false; + + currentInfo = info; + currentVkBuffer = vkBuffer; + } } SignalDirty(DirtyFlags.Storage); @@ -194,14 +212,25 @@ namespace Ryujinx.Graphics.Vulkan for (int i = 0; i < buffers.Length; i++) { var buffer = buffers[i]; + int index = first + i; - _uniformBufferRefs[first + i] = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false); + Auto vkBuffer = _gd.BufferManager.GetBuffer(commandBuffer, buffer.Handle, false); + ref Auto currentVkBuffer = ref _uniformBufferRefs[index]; - _uniformBuffers[first + i] = new DescriptorBufferInfo() + DescriptorBufferInfo info = new DescriptorBufferInfo() { Offset = (ulong)buffer.Offset, Range = (ulong)buffer.Size }; + ref DescriptorBufferInfo currentInfo = ref _uniformBuffers[index]; + + if (vkBuffer != currentVkBuffer || currentInfo.Offset != info.Offset || currentInfo.Range != info.Range) + { + _uniformSet[index] = false; + + currentInfo = info; + currentVkBuffer = vkBuffer; + } } SignalDirty(DirtyFlags.Uniform); @@ -294,11 +323,17 @@ namespace Ryujinx.Graphics.Vulkan { Span uniformBuffer = stackalloc DescriptorBufferInfo[1]; + if (!_uniformSet[0]) + { + _cachedSupportBuffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value; + _uniformSet[0] = true; + } + uniformBuffer[0] = new DescriptorBufferInfo() { Offset = 0, Range = (ulong)SupportBuffer.RequiredSize, - Buffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value + Buffer = _cachedSupportBuffer }; dsc.UpdateBuffers(0, 0, uniformBuffer, DescriptorType.UniformBuffer); @@ -325,7 +360,14 @@ namespace Ryujinx.Graphics.Vulkan { for (int i = 0; i < count; i++) { - UpdateBuffer(cbs, ref _uniformBuffers[binding + i], _uniformBufferRefs[binding + i], dummyBuffer); + int index = binding + i; + + if (!_uniformSet[index]) + { + UpdateBuffer(cbs, ref _uniformBuffers[index], _uniformBufferRefs[index], dummyBuffer); + + _uniformSet[index] = true; + } } ReadOnlySpan uniformBuffers = _uniformBuffers; @@ -335,7 +377,14 @@ namespace Ryujinx.Graphics.Vulkan { for (int i = 0; i < count; i++) { - UpdateBuffer(cbs, ref _storageBuffers[binding + i], _storageBufferRefs[binding + i], dummyBuffer); + int index = binding + i; + + if (!_storageSet[index]) + { + UpdateBuffer(cbs, ref _storageBuffers[index], _storageBufferRefs[index], dummyBuffer); + + _storageSet[index] = true; + } } ReadOnlySpan storageBuffers = _storageBuffers; @@ -442,16 +491,21 @@ namespace Ryujinx.Graphics.Vulkan var dummyBuffer = _dummyBuffer?.GetBuffer(); int stagesCount = _program.Bindings[PipelineBase.UniformSetIndex].Length; - Span uniformBuffer = stackalloc DescriptorBufferInfo[1]; - - uniformBuffer[0] = new DescriptorBufferInfo() + if (!_uniformSet[0]) { - Offset = 0, - Range = (ulong)SupportBuffer.RequiredSize, - Buffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value - }; + Span uniformBuffer = stackalloc DescriptorBufferInfo[1]; - UpdateBuffers(cbs, pbp, 0, uniformBuffer, DescriptorType.UniformBuffer); + uniformBuffer[0] = new DescriptorBufferInfo() + { + Offset = 0, + Range = (ulong)SupportBuffer.RequiredSize, + Buffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value + }; + + _uniformSet[0] = true; + + UpdateBuffers(cbs, pbp, 0, uniformBuffer, DescriptorType.UniformBuffer); + } for (int stageIndex = 0; stageIndex < stagesCount; stageIndex++) { @@ -469,13 +523,25 @@ namespace Ryujinx.Graphics.Vulkan count++; } + bool doUpdate = false; + for (int i = 0; i < count; i++) { - UpdateBuffer(cbs, ref _uniformBuffers[binding + i], _uniformBufferRefs[binding + i], dummyBuffer); + int index = binding + i; + + if (!_uniformSet[index]) + { + UpdateBuffer(cbs, ref _uniformBuffers[index], _uniformBufferRefs[index], dummyBuffer); + _uniformSet[index] = true; + doUpdate = true; + } } - ReadOnlySpan uniformBuffers = _uniformBuffers; - UpdateBuffers(cbs, pbp, binding, uniformBuffers.Slice(binding, count), DescriptorType.UniformBuffer); + if (doUpdate) + { + ReadOnlySpan uniformBuffers = _uniformBuffers; + UpdateBuffers(cbs, pbp, binding, uniformBuffers.Slice(binding, count), DescriptorType.UniformBuffer); + } } } } @@ -516,6 +582,9 @@ namespace Ryujinx.Graphics.Vulkan public void SignalCommandBufferChange() { _dirty = DirtyFlags.All; + + Array.Clear(_uniformSet); + Array.Clear(_storageSet); } protected virtual void Dispose(bool disposing) diff --git a/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs index 456691261..499bd3b24 100644 --- a/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs +++ b/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs @@ -8,6 +8,7 @@ namespace Ryujinx.Graphics.Vulkan public readonly bool SupportsExtendedDynamicState; public readonly bool SupportsMultiView; public readonly bool SupportsNullDescriptors; + public readonly bool SupportsPushDescriptors; public readonly bool SupportsTransformFeedback; public readonly bool SupportsTransformFeedbackQueries; public readonly bool SupportsGeometryShader; @@ -20,6 +21,7 @@ namespace Ryujinx.Graphics.Vulkan bool supportsExtendedDynamicState, bool supportsMultiView, bool supportsNullDescriptors, + bool supportsPushDescriptors, bool supportsTransformFeedback, bool supportsTransformFeedbackQueries, bool supportsGeometryShader, @@ -31,6 +33,7 @@ namespace Ryujinx.Graphics.Vulkan SupportsExtendedDynamicState = supportsExtendedDynamicState; SupportsMultiView = supportsMultiView; SupportsNullDescriptors = supportsNullDescriptors; + SupportsPushDescriptors = supportsPushDescriptors; SupportsTransformFeedback = supportsTransformFeedback; SupportsTransformFeedbackQueries = supportsTransformFeedbackQueries; SupportsGeometryShader = supportsGeometryShader; diff --git a/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index cd911ce23..a0cca76c4 100644 --- a/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -90,7 +90,7 @@ namespace Ryujinx.Graphics.Vulkan _shaders = internalShaders; - bool usePd = !isMinimal && VulkanConfiguration.UsePushDescriptors; + bool usePd = !isMinimal && VulkanConfiguration.UsePushDescriptors && _gd.Capabilities.SupportsPushDescriptors; _plce = isMinimal ? gd.PipelineLayoutCache.Create(gd, device, shaders) diff --git a/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs b/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs index a85a12dd5..2025d0f81 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanGraphicsDevice.cs @@ -212,6 +212,7 @@ namespace Ryujinx.Graphics.Vulkan supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName), features2.Features.MultiViewport, featuresRobustness2.NullDescriptor, + supportedExtensions.Contains(KhrPushDescriptor.ExtensionName), supportsTransformFeedback, propertiesTransformFeedback.TransformFeedbackQueries, supportedFeatures.GeometryShader,