CachedShaderBindings.cs
1 using Ryujinx.Graphics.GAL; 2 using Ryujinx.Graphics.Gpu.Engine; 3 using Ryujinx.Graphics.Gpu.Image; 4 using Ryujinx.Graphics.Shader; 5 using System; 6 using System.Linq; 7 8 namespace Ryujinx.Graphics.Gpu.Shader 9 { 10 /// <summary> 11 /// A collection of shader bindings ready for insertion into the buffer and texture managers. 12 /// </summary> 13 internal class CachedShaderBindings 14 { 15 public TextureBindingInfo[][] TextureBindings { get; } 16 public TextureBindingInfo[][] ImageBindings { get; } 17 public BufferDescriptor[][] ConstantBufferBindings { get; } 18 public BufferDescriptor[][] StorageBufferBindings { get; } 19 20 public int[] TextureCounts { get; } 21 22 public int MaxTextureBinding { get; } 23 public int MaxImageBinding { get; } 24 25 /// <summary> 26 /// Create a new cached shader bindings collection. 27 /// </summary> 28 /// <param name="isCompute">Whether the shader is for compute</param> 29 /// <param name="stages">The stages used by the shader</param> 30 public CachedShaderBindings(bool isCompute, CachedShaderStage[] stages) 31 { 32 int stageCount = isCompute ? 1 : Constants.ShaderStages; 33 34 TextureBindings = new TextureBindingInfo[stageCount][]; 35 ImageBindings = new TextureBindingInfo[stageCount][]; 36 ConstantBufferBindings = new BufferDescriptor[stageCount][]; 37 StorageBufferBindings = new BufferDescriptor[stageCount][]; 38 39 TextureCounts = new int[stageCount]; 40 41 int maxTextureBinding = -1; 42 int maxImageBinding = -1; 43 int offset = isCompute ? 0 : 1; 44 45 for (int i = 0; i < stageCount; i++) 46 { 47 CachedShaderStage stage = stages[i + offset]; 48 49 if (stage == null) 50 { 51 TextureBindings[i] = Array.Empty<TextureBindingInfo>(); 52 ImageBindings[i] = Array.Empty<TextureBindingInfo>(); 53 ConstantBufferBindings[i] = Array.Empty<BufferDescriptor>(); 54 StorageBufferBindings[i] = Array.Empty<BufferDescriptor>(); 55 56 continue; 57 } 58 59 TextureBindings[i] = stage.Info.Textures.Select(descriptor => 60 { 61 Target target = descriptor.Type != SamplerType.None ? ShaderTexture.GetTarget(descriptor.Type) : default; 62 63 var result = new TextureBindingInfo( 64 target, 65 descriptor.Set, 66 descriptor.Binding, 67 descriptor.ArrayLength, 68 descriptor.CbufSlot, 69 descriptor.HandleIndex, 70 descriptor.Flags, 71 descriptor.Type == SamplerType.None); 72 73 if (descriptor.ArrayLength <= 1) 74 { 75 if (descriptor.Binding > maxTextureBinding) 76 { 77 maxTextureBinding = descriptor.Binding; 78 } 79 80 TextureCounts[i]++; 81 } 82 83 return result; 84 }).ToArray(); 85 86 ImageBindings[i] = stage.Info.Images.Select(descriptor => 87 { 88 Target target = ShaderTexture.GetTarget(descriptor.Type); 89 FormatInfo formatInfo = ShaderTexture.GetFormatInfo(descriptor.Format); 90 91 var result = new TextureBindingInfo( 92 target, 93 formatInfo, 94 descriptor.Set, 95 descriptor.Binding, 96 descriptor.ArrayLength, 97 descriptor.CbufSlot, 98 descriptor.HandleIndex, 99 descriptor.Flags); 100 101 if (descriptor.ArrayLength <= 1 && descriptor.Binding > maxImageBinding) 102 { 103 maxImageBinding = descriptor.Binding; 104 } 105 106 return result; 107 }).ToArray(); 108 109 ConstantBufferBindings[i] = stage.Info.CBuffers.ToArray(); 110 StorageBufferBindings[i] = stage.Info.SBuffers.ToArray(); 111 } 112 113 MaxTextureBinding = maxTextureBinding; 114 MaxImageBinding = maxImageBinding; 115 } 116 } 117 }