diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /Ryujinx.Graphics.Vulkan/ShaderCollection.cs | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/ShaderCollection.cs')
| -rw-r--r-- | Ryujinx.Graphics.Vulkan/ShaderCollection.cs | 427 |
1 files changed, 0 insertions, 427 deletions
diff --git a/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/Ryujinx.Graphics.Vulkan/ShaderCollection.cs deleted file mode 100644 index 1694049c..00000000 --- a/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ /dev/null @@ -1,427 +0,0 @@ -using Ryujinx.Common.Logging; -using Ryujinx.Graphics.GAL; -using Silk.NET.Vulkan; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace Ryujinx.Graphics.Vulkan -{ - class ShaderCollection : IProgram - { - private readonly PipelineShaderStageCreateInfo[] _infos; - private readonly Shader[] _shaders; - - private readonly PipelineLayoutCacheEntry _plce; - - public PipelineLayout PipelineLayout => _plce.PipelineLayout; - - public bool HasMinimalLayout { get; } - public bool UsePushDescriptors { get; } - public bool IsCompute { get; } - - public uint Stages { get; } - - public int[][][] Bindings { get; } - - public ProgramLinkStatus LinkStatus { get; private set; } - - public readonly SpecDescription[] SpecDescriptions; - - public bool IsLinked - { - get - { - if (LinkStatus == ProgramLinkStatus.Incomplete) - { - CheckProgramLink(true); - } - - return LinkStatus == ProgramLinkStatus.Success; - } - } - - private HashTableSlim<PipelineUid, Auto<DisposablePipeline>> _graphicsPipelineCache; - private HashTableSlim<SpecData, Auto<DisposablePipeline>> _computePipelineCache; - - private VulkanRenderer _gd; - private Device _device; - private bool _initialized; - - private ProgramPipelineState _state; - private DisposableRenderPass _dummyRenderPass; - private Task _compileTask; - private bool _firstBackgroundUse; - - public ShaderCollection(VulkanRenderer gd, Device device, ShaderSource[] shaders, SpecDescription[] specDescription = null, bool isMinimal = false) - { - _gd = gd; - _device = device; - - if (specDescription != null && specDescription.Length != shaders.Length) - { - throw new ArgumentException($"{nameof(specDescription)} array length must match {nameof(shaders)} array if provided"); - } - - gd.Shaders.Add(this); - - var internalShaders = new Shader[shaders.Length]; - - _infos = new PipelineShaderStageCreateInfo[shaders.Length]; - - SpecDescriptions = specDescription; - - LinkStatus = ProgramLinkStatus.Incomplete; - - uint stages = 0; - - for (int i = 0; i < shaders.Length; i++) - { - var shader = new Shader(gd.Api, device, shaders[i]); - - stages |= 1u << shader.StageFlags switch - { - ShaderStageFlags.FragmentBit => 1, - ShaderStageFlags.GeometryBit => 2, - ShaderStageFlags.TessellationControlBit => 3, - ShaderStageFlags.TessellationEvaluationBit => 4, - _ => 0 - }; - - if (shader.StageFlags == ShaderStageFlags.ComputeBit) - { - IsCompute = true; - } - - internalShaders[i] = shader; - } - - _shaders = internalShaders; - - bool usePd = !isMinimal && VulkanConfiguration.UsePushDescriptors && _gd.Capabilities.SupportsPushDescriptors; - - _plce = isMinimal - ? gd.PipelineLayoutCache.Create(gd, device, shaders) - : gd.PipelineLayoutCache.GetOrCreate(gd, device, stages, usePd); - - HasMinimalLayout = isMinimal; - UsePushDescriptors = usePd; - - 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) - }; - - _compileTask = Task.CompletedTask; - _firstBackgroundUse = false; - } - - public ShaderCollection( - VulkanRenderer gd, - Device device, - ShaderSource[] sources, - ProgramPipelineState state, - bool fromCache) : this(gd, device, sources) - { - _state = state; - - _compileTask = BackgroundCompilation(); - _firstBackgroundUse = !fromCache; - } - - private async Task BackgroundCompilation() - { - await Task.WhenAll(_shaders.Select(shader => shader.CompileTask)); - - if (_shaders.Any(shader => shader.CompileStatus == ProgramLinkStatus.Failure)) - { - LinkStatus = ProgramLinkStatus.Failure; - - return; - } - - try - { - if (IsCompute) - { - CreateBackgroundComputePipeline(); - } - else - { - CreateBackgroundGraphicsPipeline(); - } - } - catch (VulkanException e) - { - Logger.Error?.PrintMsg(LogClass.Gpu, $"Background Compilation failed: {e.Message}"); - - LinkStatus = ProgramLinkStatus.Failure; - } - } - - private void EnsureShadersReady() - { - if (!_initialized) - { - CheckProgramLink(true); - - ProgramLinkStatus resultStatus = ProgramLinkStatus.Success; - - for (int i = 0; i < _shaders.Length; i++) - { - var shader = _shaders[i]; - - if (shader.CompileStatus != ProgramLinkStatus.Success) - { - resultStatus = ProgramLinkStatus.Failure; - } - - _infos[i] = shader.GetInfo(); - } - - // If the link status was already set as failure by background compilation, prefer that decision. - if (LinkStatus != ProgramLinkStatus.Failure) - { - LinkStatus = resultStatus; - } - - _initialized = true; - } - } - - public PipelineShaderStageCreateInfo[] GetInfos() - { - EnsureShadersReady(); - - return _infos; - } - - protected unsafe DisposableRenderPass CreateDummyRenderPass() - { - if (_dummyRenderPass.Value.Handle != 0) - { - return _dummyRenderPass; - } - - return _dummyRenderPass = _state.ToRenderPass(_gd, _device); - } - - public void CreateBackgroundComputePipeline() - { - PipelineState pipeline = new PipelineState(); - pipeline.Initialize(); - - pipeline.Stages[0] = _shaders[0].GetInfo(); - pipeline.StagesCount = 1; - pipeline.PipelineLayout = PipelineLayout; - - pipeline.CreateComputePipeline(_gd, _device, this, (_gd.Pipeline as PipelineBase).PipelineCache); - pipeline.Dispose(); - } - - public void CreateBackgroundGraphicsPipeline() - { - // To compile shaders in the background in Vulkan, we need to create valid pipelines using the shader modules. - // The GPU provides pipeline state via the GAL that can be converted into our internal Vulkan pipeline state. - // This should match the pipeline state at the time of the first draw. If it doesn't, then it'll likely be - // close enough that the GPU driver will reuse the compiled shader for the different state. - - // First, we need to create a render pass object compatible with the one that will be used at runtime. - // The active attachment formats have been provided by the abstraction layer. - var renderPass = CreateDummyRenderPass(); - - PipelineState pipeline = _state.ToVulkanPipelineState(_gd); - - // Copy the shader stage info to the pipeline. - var stages = pipeline.Stages.AsSpan(); - - for (int i = 0; i < _shaders.Length; i++) - { - stages[i] = _shaders[i].GetInfo(); - } - - pipeline.StagesCount = (uint)_shaders.Length; - pipeline.PipelineLayout = PipelineLayout; - - pipeline.CreateGraphicsPipeline(_gd, _device, this, (_gd.Pipeline as PipelineBase).PipelineCache, renderPass.Value); - pipeline.Dispose(); - } - - public ProgramLinkStatus CheckProgramLink(bool blocking) - { - if (LinkStatus == ProgramLinkStatus.Incomplete) - { - ProgramLinkStatus resultStatus = ProgramLinkStatus.Success; - - foreach (Shader shader in _shaders) - { - if (shader.CompileStatus == ProgramLinkStatus.Incomplete) - { - if (blocking) - { - // Wait for this shader to finish compiling. - shader.WaitForCompile(); - - if (shader.CompileStatus != ProgramLinkStatus.Success) - { - resultStatus = ProgramLinkStatus.Failure; - } - } - else - { - return ProgramLinkStatus.Incomplete; - } - } - } - - if (!_compileTask.IsCompleted) - { - if (blocking) - { - _compileTask.Wait(); - - if (LinkStatus == ProgramLinkStatus.Failure) - { - return ProgramLinkStatus.Failure; - } - } - else - { - return ProgramLinkStatus.Incomplete; - } - } - - return resultStatus; - } - - return LinkStatus; - } - - public byte[] GetBinary() - { - return null; - } - - public void AddComputePipeline(ref SpecData key, Auto<DisposablePipeline> pipeline) - { - (_computePipelineCache ??= new()).Add(ref key, pipeline); - } - - public void AddGraphicsPipeline(ref PipelineUid key, Auto<DisposablePipeline> pipeline) - { - (_graphicsPipelineCache ??= new()).Add(ref key, pipeline); - } - - public bool TryGetComputePipeline(ref SpecData key, out Auto<DisposablePipeline> pipeline) - { - if (_computePipelineCache == null) - { - pipeline = default; - return false; - } - - if (_computePipelineCache.TryGetValue(ref key, out pipeline)) - { - return true; - } - - return false; - } - - public bool TryGetGraphicsPipeline(ref PipelineUid key, out Auto<DisposablePipeline> pipeline) - { - if (_graphicsPipelineCache == null) - { - pipeline = default; - return false; - } - - if (!_graphicsPipelineCache.TryGetValue(ref key, out pipeline)) - { - if (_firstBackgroundUse) - { - Logger.Warning?.Print(LogClass.Gpu, "Background pipeline compile missed on draw - incorrect pipeline state?"); - _firstBackgroundUse = false; - } - - return false; - } - - _firstBackgroundUse = false; - - return true; - } - - public Auto<DescriptorSetCollection> GetNewDescriptorSetCollection( - VulkanRenderer gd, - int commandBufferIndex, - int setIndex, - out bool isNew) - { - return _plce.GetNewDescriptorSetCollection(gd, commandBufferIndex, setIndex, out isNew); - } - - protected virtual unsafe void Dispose(bool disposing) - { - if (disposing) - { - if (!_gd.Shaders.Remove(this)) - { - return; - } - - for (int i = 0; i < _shaders.Length; i++) - { - _shaders[i].Dispose(); - } - - if (_graphicsPipelineCache != null) - { - foreach (Auto<DisposablePipeline> pipeline in _graphicsPipelineCache.Values) - { - pipeline.Dispose(); - } - } - - if (_computePipelineCache != null) - { - foreach (Auto<DisposablePipeline> pipeline in _computePipelineCache.Values) - { - pipeline.Dispose(); - } - } - - if (_dummyRenderPass.Value.Handle != 0) - { - _dummyRenderPass.Dispose(); - } - } - } - - public void Dispose() - { - Dispose(true); - } - } -} |
