aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs')
-rw-r--r--src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs106
1 files changed, 76 insertions, 30 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs
index 1694049c..334dfc20 100644
--- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs
+++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs
@@ -3,6 +3,7 @@ using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
@@ -23,7 +24,7 @@ namespace Ryujinx.Graphics.Vulkan
public uint Stages { get; }
- public int[][][] Bindings { get; }
+ public ResourceBindingSegment[][] BindingSegments { get; }
public ProgramLinkStatus LinkStatus { get; private set; }
@@ -54,7 +55,13 @@ namespace Ryujinx.Graphics.Vulkan
private Task _compileTask;
private bool _firstBackgroundUse;
- public ShaderCollection(VulkanRenderer gd, Device device, ShaderSource[] shaders, SpecDescription[] specDescription = null, bool isMinimal = false)
+ public ShaderCollection(
+ VulkanRenderer gd,
+ Device device,
+ ShaderSource[] shaders,
+ ResourceLayout resourceLayout,
+ SpecDescription[] specDescription = null,
+ bool isMinimal = false)
{
_gd = gd;
_device = device;
@@ -99,39 +106,16 @@ namespace Ryujinx.Graphics.Vulkan
_shaders = internalShaders;
- bool usePd = !isMinimal && VulkanConfiguration.UsePushDescriptors && _gd.Capabilities.SupportsPushDescriptors;
+ bool usePushDescriptors = !isMinimal && VulkanConfiguration.UsePushDescriptors && _gd.Capabilities.SupportsPushDescriptors;
- _plce = isMinimal
- ? gd.PipelineLayoutCache.Create(gd, device, shaders)
- : gd.PipelineLayoutCache.GetOrCreate(gd, device, stages, usePd);
+ _plce = gd.PipelineLayoutCache.GetOrCreate(gd, device, resourceLayout.Sets, usePushDescriptors);
HasMinimalLayout = isMinimal;
- UsePushDescriptors = usePd;
+ UsePushDescriptors = usePushDescriptors;
Stages = stages;
- int[][] GrabAll(Func<ShaderBindings, IReadOnlyCollection<int>> selector)
- {
- bool hasAny = false;
- int[][] bindings = new int[internalShaders.Length][];
-
- for (int i = 0; i < internalShaders.Length; i++)
- {
- var collection = selector(internalShaders[i].Bindings);
- hasAny |= collection.Count != 0;
- bindings[i] = collection.ToArray();
- }
-
- return hasAny ? bindings : Array.Empty<int[]>();
- }
-
- Bindings = new[]
- {
- GrabAll(x => x.UniformBufferBindings),
- GrabAll(x => x.StorageBufferBindings),
- GrabAll(x => x.TextureBindings),
- GrabAll(x => x.ImageBindings)
- };
+ BindingSegments = BuildBindingSegments(resourceLayout.SetUsages);
_compileTask = Task.CompletedTask;
_firstBackgroundUse = false;
@@ -141,8 +125,9 @@ namespace Ryujinx.Graphics.Vulkan
VulkanRenderer gd,
Device device,
ShaderSource[] sources,
+ ResourceLayout resourceLayout,
ProgramPipelineState state,
- bool fromCache) : this(gd, device, sources)
+ bool fromCache) : this(gd, device, sources, resourceLayout)
{
_state = state;
@@ -150,6 +135,67 @@ namespace Ryujinx.Graphics.Vulkan
_firstBackgroundUse = !fromCache;
}
+ private static ResourceBindingSegment[][] BuildBindingSegments(ReadOnlyCollection<ResourceUsageCollection> setUsages)
+ {
+ ResourceBindingSegment[][] segments = new ResourceBindingSegment[setUsages.Count][];
+
+ for (int setIndex = 0; setIndex < setUsages.Count; setIndex++)
+ {
+ List<ResourceBindingSegment> currentSegments = new List<ResourceBindingSegment>();
+
+ ResourceUsage currentUsage = default;
+ int currentCount = 0;
+
+ for (int index = 0; index < setUsages[setIndex].Usages.Count; index++)
+ {
+ ResourceUsage usage = setUsages[setIndex].Usages[index];
+
+ // If the resource is not accessed, we don't need to update it.
+ if (usage.Access == ResourceAccess.None)
+ {
+ continue;
+ }
+
+ if (currentUsage.Binding + currentCount != usage.Binding ||
+ currentUsage.Type != usage.Type ||
+ currentUsage.Stages != usage.Stages ||
+ currentUsage.Access != usage.Access)
+ {
+ if (currentCount != 0)
+ {
+ currentSegments.Add(new ResourceBindingSegment(
+ currentUsage.Binding,
+ currentCount,
+ currentUsage.Type,
+ currentUsage.Stages,
+ currentUsage.Access));
+ }
+
+ currentUsage = usage;
+ currentCount = 1;
+ }
+ else
+ {
+ currentCount++;
+ }
+ }
+
+ if (currentCount != 0)
+ {
+ currentSegments.Add(new ResourceBindingSegment(
+ currentUsage.Binding,
+ currentCount,
+ currentUsage.Type,
+ currentUsage.Stages,
+ currentUsage.Access));
+ }
+
+ segments[setIndex] = currentSegments.ToArray();
+ }
+
+ return segments;
+ }
+
private async Task BackgroundCompilation()
{
await Task.WhenAll(_shaders.Select(shader => shader.CompileTask));