diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation')
12 files changed, 363 insertions, 138 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs b/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs index 24993e00..b1b40f65 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs @@ -22,4 +22,35 @@ Array = 1 << 10 } + + static class AggregateTypeExtensions + { + public static int GetSizeInBytes(this AggregateType type) + { + int elementSize = (type & AggregateType.ElementTypeMask) switch + { + AggregateType.Bool or + AggregateType.FP32 or + AggregateType.S32 or + AggregateType.U32 => 4, + AggregateType.FP64 => 8, + _ => 0 + }; + + switch (type & AggregateType.ElementCountMask) + { + case AggregateType.Vector2: + elementSize *= 2; + break; + case AggregateType.Vector3: + elementSize *= 3; + break; + case AggregateType.Vector4: + elementSize *= 4; + break; + } + + return elementSize; + } + } } diff --git a/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs index 112baccf..0c51b16f 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs @@ -234,8 +234,8 @@ namespace Ryujinx.Graphics.Shader.Translation { Operand x = this.Load(StorageKind.Output, IoVariable.Position, null, Const(0)); Operand y = this.Load(StorageKind.Output, IoVariable.Position, null, Const(1)); - Operand xScale = this.Load(StorageKind.Input, IoVariable.SupportBlockViewInverse, null, Const(0)); - Operand yScale = this.Load(StorageKind.Input, IoVariable.SupportBlockViewInverse, null, Const(1)); + Operand xScale = this.Load(StorageKind.ConstantBuffer, SupportBuffer.Binding, Const((int)SupportBufferField.ViewportInverse), Const(0)); + Operand yScale = this.Load(StorageKind.ConstantBuffer, SupportBuffer.Binding, Const((int)SupportBufferField.ViewportInverse), Const(1)); Operand negativeOne = ConstF(-1.0f); this.Store(StorageKind.Output, IoVariable.Position, null, Const(0), this.FPFusedMultiplyAdd(x, xScale, negativeOne)); @@ -420,7 +420,7 @@ namespace Ryujinx.Graphics.Shader.Translation // Perform B <-> R swap if needed, for BGRA formats (not supported on OpenGL). if (!supportsBgra && (component == 0 || component == 2)) { - Operand isBgra = this.Load(StorageKind.Input, IoVariable.FragmentOutputIsBgra, null, Const(rtIndex)); + Operand isBgra = this.Load(StorageKind.ConstantBuffer, SupportBuffer.Binding, Const((int)SupportBufferField.FragmentIsBgra), Const(rtIndex)); Operand lblIsBgra = Label(); Operand lblEnd = Label(); diff --git a/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs index 93748249..e41a28f1 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs @@ -549,11 +549,31 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(fpType | Instruction.IsNan, Local(), a); } + public static Operand Load(this EmitterContext context, StorageKind storageKind, int binding) + { + return context.Add(Instruction.Load, storageKind, Local(), Const(binding)); + } + + public static Operand Load(this EmitterContext context, StorageKind storageKind, int binding, Operand e0) + { + return context.Add(Instruction.Load, storageKind, Local(), Const(binding), e0); + } + + public static Operand Load(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1) + { + return context.Add(Instruction.Load, storageKind, Local(), Const(binding), e0, e1); + } + + public static Operand Load(this EmitterContext context, StorageKind storageKind, int binding, Operand e0, Operand e1, Operand e2) + { + return context.Add(Instruction.Load, storageKind, Local(), Const(binding), e0, e1, e2); + } + public static Operand Load(this EmitterContext context, StorageKind storageKind, IoVariable ioVariable, Operand primVertex = null) { return primVertex != null - ? context.Add(Instruction.Load, storageKind, Local(), Const((int)ioVariable), primVertex) - : context.Add(Instruction.Load, storageKind, Local(), Const((int)ioVariable)); + ? context.Load(storageKind, (int)ioVariable, primVertex) + : context.Load(storageKind, (int)ioVariable); } public static Operand Load( @@ -564,8 +584,8 @@ namespace Ryujinx.Graphics.Shader.Translation Operand elemIndex) { return primVertex != null - ? context.Add(Instruction.Load, storageKind, Local(), Const((int)ioVariable), primVertex, elemIndex) - : context.Add(Instruction.Load, storageKind, Local(), Const((int)ioVariable), elemIndex); + ? context.Load(storageKind, (int)ioVariable, primVertex, elemIndex) + : context.Load(storageKind, (int)ioVariable, elemIndex); } public static Operand Load( @@ -577,22 +597,8 @@ namespace Ryujinx.Graphics.Shader.Translation Operand elemIndex) { return primVertex != null - ? context.Add(Instruction.Load, storageKind, Local(), Const((int)ioVariable), primVertex, arrayIndex, elemIndex) - : context.Add(Instruction.Load, storageKind, Local(), Const((int)ioVariable), arrayIndex, elemIndex); - } - - public static Operand LoadConstant(this EmitterContext context, Operand a, Operand b) - { - if (a.Type == OperandType.Constant) - { - context.Config.SetUsedConstantBuffer(a.Value); - } - else - { - context.Config.SetUsedFeature(FeatureFlags.CbIndexing); - } - - return context.Add(Instruction.LoadConstant, Local(), a, b); + ? context.Load(storageKind, (int)ioVariable, primVertex, arrayIndex, elemIndex) + : context.Load(storageKind, (int)ioVariable, arrayIndex, elemIndex); } public static Operand LoadGlobal(this EmitterContext context, Operand a, Operand b) diff --git a/src/Ryujinx.Graphics.Shader/Translation/FeatureFlags.cs b/src/Ryujinx.Graphics.Shader/Translation/FeatureFlags.cs index c035f212..e55ed13d 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/FeatureFlags.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/FeatureFlags.cs @@ -19,7 +19,6 @@ namespace Ryujinx.Graphics.Shader.Translation InstanceId = 1 << 3, DrawParameters = 1 << 4, RtLayer = 1 << 5, - CbIndexing = 1 << 6, IaIndexing = 1 << 7, OaIndexing = 1 << 8, FixedFuncAttr = 1 << 9 diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs index ca46a1f5..9a3ae1b8 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/BindlessToIndexed.cs @@ -32,25 +32,49 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations continue; } - if (handleAsgOp.Inst != Instruction.LoadConstant) + if (handleAsgOp.Inst != Instruction.Load || + handleAsgOp.StorageKind != StorageKind.ConstantBuffer || + handleAsgOp.SourcesCount != 4) { continue; } Operand ldcSrc0 = handleAsgOp.GetSource(0); + + if (ldcSrc0.Type != OperandType.Constant || + !config.ResourceManager.TryGetConstantBufferSlot(ldcSrc0.Value, out int src0CbufSlot) || + src0CbufSlot != 2) + { + continue; + } + Operand ldcSrc1 = handleAsgOp.GetSource(1); - if (ldcSrc0.Type != OperandType.Constant || ldcSrc0.Value != 2) + // We expect field index 0 to be accessed. + if (ldcSrc1.Type != OperandType.Constant || ldcSrc1.Value != 0) + { + continue; + } + + Operand ldcSrc2 = handleAsgOp.GetSource(2); + + // FIXME: This is missing some checks, for example, a check to ensure that the shift value is 2. + // Might be not worth fixing since if that doesn't kick in, the result will be no texture + // to access anyway which is also wrong. + // Plus this whole transform is fundamentally flawed as-is since we have no way to know the array size. + // Eventually, this should be entirely removed in favor of a implementation that supports true bindless + // texture access. + if (!(ldcSrc2.AsgOp is Operation shrOp) || shrOp.Inst != Instruction.ShiftRightU32) { continue; } - if (!(ldcSrc1.AsgOp is Operation shrOp) || shrOp.Inst != Instruction.ShiftRightU32) + if (!(shrOp.GetSource(0).AsgOp is Operation shrOp2) || shrOp2.Inst != Instruction.ShiftRightU32) { continue; } - if (!(shrOp.GetSource(0).AsgOp is Operation addOp) || addOp.Inst != Instruction.Add) + if (!(shrOp2.GetSource(0).AsgOp is Operation addOp) || addOp.Inst != Instruction.Add) { continue; } diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs index 6729f077..4caadb73 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/ConstantFolding.cs @@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { static class ConstantFolding { - public static void RunPass(Operation operation) + public static void RunPass(ShaderConfig config, Operation operation) { if (!AreAllSourcesConstant(operation)) { @@ -153,8 +153,21 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations EvaluateFPUnary(operation, (x) => float.IsNaN(x)); break; - case Instruction.LoadConstant: - operation.TurnIntoCopy(Cbuf(operation.GetSource(0).Value, operation.GetSource(1).Value)); + case Instruction.Load: + if (operation.StorageKind == StorageKind.ConstantBuffer && operation.SourcesCount == 4) + { + int binding = operation.GetSource(0).Value; + int fieldIndex = operation.GetSource(1).Value; + + if (config.ResourceManager.TryGetConstantBufferSlot(binding, out int cbufSlot) && fieldIndex == 0) + { + int vecIndex = operation.GetSource(2).Value; + int elemIndex = operation.GetSource(3).Value; + int cbufOffset = vecIndex * 4 + elemIndex; + + operation.TurnIntoCopy(Cbuf(cbufSlot, cbufOffset)); + } + } break; case Instruction.Maximum: diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs index 774d3e36..7758b4c6 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/GlobalToStorage.cs @@ -347,21 +347,23 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations return wordOffset; } - Operand[] sources = new Operand[operation.SourcesCount]; + Operand cbufOffset = GetCbufOffset(); + Operand vecIndex = Local(); + Operand elemIndex = Local(); - int cbSlot = UbeFirstCbuf + storageIndex; + node.List.AddBefore(node, new Operation(Instruction.ShiftRightU32, 0, vecIndex, cbufOffset, Const(2))); + node.List.AddBefore(node, new Operation(Instruction.BitwiseAnd, 0, elemIndex, cbufOffset, Const(3))); - sources[0] = Const(cbSlot); - sources[1] = GetCbufOffset(); + Operand[] sources = new Operand[4]; - config.SetUsedConstantBuffer(cbSlot); + int cbSlot = UbeFirstCbuf + storageIndex; - for (int index = 2; index < operation.SourcesCount; index++) - { - sources[index] = operation.GetSource(index); - } + sources[0] = Const(config.ResourceManager.GetConstantBufferBinding(cbSlot)); + sources[1] = Const(0); + sources[2] = vecIndex; + sources[3] = elemIndex; - Operation ldcOp = new Operation(Instruction.LoadConstant, operation.Dest, sources); + Operation ldcOp = new Operation(Instruction.Load, StorageKind.ConstantBuffer, operation.Dest, sources); for (int index = 0; index < operation.SourcesCount; index++) { diff --git a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs index b41e47e4..b126e2c4 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Optimizations/Optimizer.cs @@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations { public static void RunPass(BasicBlock[] blocks, ShaderConfig config) { - RunOptimizationPasses(blocks); + RunOptimizationPasses(blocks, config); int sbUseMask = 0; int ubeUseMask = 0; @@ -31,10 +31,10 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations config.SetAccessibleBufferMasks(sbUseMask, ubeUseMask); // Run optimizations one last time to remove any code that is now optimizable after above passes. - RunOptimizationPasses(blocks); + RunOptimizationPasses(blocks, config); } - private static void RunOptimizationPasses(BasicBlock[] blocks) + private static void RunOptimizationPasses(BasicBlock[] blocks, ShaderConfig config) { bool modified; @@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations continue; } - ConstantFolding.RunPass(operation); + ConstantFolding.RunPass(config, operation); Simplification.RunPass(operation); if (DestIsLocalVar(operation)) diff --git a/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs new file mode 100644 index 00000000..b31790d3 --- /dev/null +++ b/src/Ryujinx.Graphics.Shader/Translation/ResourceManager.cs @@ -0,0 +1,126 @@ +using Ryujinx.Graphics.Shader.StructuredIr; +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace Ryujinx.Graphics.Shader.Translation +{ + class ResourceManager + { + private static readonly string[] _stagePrefixes = new string[] { "cp", "vp", "tcp", "tep", "gp", "fp" }; + + private readonly IGpuAccessor _gpuAccessor; + private readonly ShaderProperties _properties; + private readonly string _stagePrefix; + + private readonly int[] _cbSlotToBindingMap; + + private readonly HashSet<int> _usedConstantBufferBindings; + + public ResourceManager(ShaderStage stage, IGpuAccessor gpuAccessor, ShaderProperties properties) + { + _gpuAccessor = gpuAccessor; + _properties = properties; + _stagePrefix = GetShaderStagePrefix(stage); + + _cbSlotToBindingMap = new int[18]; + _cbSlotToBindingMap.AsSpan().Fill(-1); + + _usedConstantBufferBindings = new HashSet<int>(); + + properties.AddConstantBuffer(0, new BufferDefinition(BufferLayout.Std140, 0, 0, "support_buffer", SupportBuffer.GetStructureType())); + } + + public int GetConstantBufferBinding(int slot) + { + int binding = _cbSlotToBindingMap[slot]; + if (binding < 0) + { + binding = _gpuAccessor.QueryBindingConstantBuffer(slot); + _cbSlotToBindingMap[slot] = binding; + string slotNumber = slot.ToString(CultureInfo.InvariantCulture); + AddNewConstantBuffer(binding, $"{_stagePrefix}_c{slotNumber}"); + } + + return binding; + } + + public bool TryGetConstantBufferSlot(int binding, out int slot) + { + for (slot = 0; slot < _cbSlotToBindingMap.Length; slot++) + { + if (_cbSlotToBindingMap[slot] == binding) + { + return true; + } + } + + slot = 0; + return false; + } + + public void SetUsedConstantBufferBinding(int binding) + { + _usedConstantBufferBindings.Add(binding); + } + + public BufferDescriptor[] GetConstantBufferDescriptors() + { + var descriptors = new BufferDescriptor[_usedConstantBufferBindings.Count]; + + int descriptorIndex = 0; + + for (int slot = 0; slot < _cbSlotToBindingMap.Length; slot++) + { + int binding = _cbSlotToBindingMap[slot]; + + if (binding >= 0 && _usedConstantBufferBindings.Contains(binding)) + { + descriptors[descriptorIndex++] = new BufferDescriptor(binding, slot); + } + } + + if (descriptors.Length != descriptorIndex) + { + Array.Resize(ref descriptors, descriptorIndex); + } + + return descriptors; + } + + private void AddNewConstantBuffer(int binding, string name) + { + StructureType type = new StructureType(new[] + { + new StructureField(AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32, "data", Constants.ConstantBufferSize / 16) + }); + + _properties.AddConstantBuffer(binding, new BufferDefinition(BufferLayout.Std140, 0, binding, name, type)); + } + + public void InheritFrom(ResourceManager other) + { + for (int i = 0; i < other._cbSlotToBindingMap.Length; i++) + { + int binding = other._cbSlotToBindingMap[i]; + + if (binding >= 0) + { + _cbSlotToBindingMap[i] = binding; + } + } + } + + public static string GetShaderStagePrefix(ShaderStage stage) + { + uint index = (uint)stage; + + if (index >= _stagePrefixes.Length) + { + return "invalid"; + } + + return _stagePrefixes[index]; + } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs b/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs index 8167efc1..711661c9 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs @@ -1,7 +1,6 @@ -using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.StructuredIr; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Numerics; @@ -16,6 +15,7 @@ namespace Ryujinx.Graphics.Shader.Translation { bool isVertexShader = config.Stage == ShaderStage.Vertex; bool hasConstantBufferDrawParameters = config.GpuAccessor.QueryHasConstantBufferDrawParameters(); + bool hasVectorIndexingBug = config.GpuAccessor.QueryHostHasVectorIndexingBug(); bool supportsSnormBufferTextureFormat = config.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat(); for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++) @@ -45,6 +45,11 @@ namespace Ryujinx.Graphics.Shader.Translation } } + if (hasVectorIndexingBug) + { + InsertVectorComponentSelect(node, config); + } + LinkedListNode<INode> nextNode = node.Next; if (operation is TextureOperation texOp) @@ -71,6 +76,84 @@ namespace Ryujinx.Graphics.Shader.Translation } } + private static void InsertVectorComponentSelect(LinkedListNode<INode> node, ShaderConfig config) + { + Operation operation = (Operation)node.Value; + + if (operation.Inst != Instruction.Load || + operation.StorageKind != StorageKind.ConstantBuffer || + operation.SourcesCount < 3) + { + return; + } + + Operand bindingIndex = operation.GetSource(0); + Operand fieldIndex = operation.GetSource(1); + Operand elemIndex = operation.GetSource(operation.SourcesCount - 1); + + if (bindingIndex.Type != OperandType.Constant || + fieldIndex.Type != OperandType.Constant || + elemIndex.Type == OperandType.Constant) + { + return; + } + + BufferDefinition buffer = config.Properties.ConstantBuffers[bindingIndex.Value]; + StructureField field = buffer.Type.Fields[fieldIndex.Value]; + + int elemCount = (field.Type & AggregateType.ElementCountMask) switch + { + AggregateType.Vector2 => 2, + AggregateType.Vector3 => 3, + AggregateType.Vector4 => 4, + _ => 1 + }; + + if (elemCount == 1) + { + return; + } + + Operand result = null; + + for (int i = 0; i < elemCount; i++) + { + Operand value = Local(); + Operand[] inputs = new Operand[operation.SourcesCount]; + + for (int srcIndex = 0; srcIndex < inputs.Length - 1; srcIndex++) + { + inputs[srcIndex] = operation.GetSource(srcIndex); + } + + inputs[inputs.Length - 1] = Const(i); + + Operation loadOp = new Operation(Instruction.Load, StorageKind.ConstantBuffer, value, inputs); + + node.List.AddBefore(node, loadOp); + + if (i == 0) + { + result = value; + } + else + { + Operand isCurrentIndex = Local(); + Operand selection = Local(); + + Operation compareOp = new Operation(Instruction.CompareEqual, isCurrentIndex, new Operand[] { elemIndex, Const(i) }); + Operation selectOp = new Operation(Instruction.ConditionalSelect, selection, new Operand[] { isCurrentIndex, value, result }); + + node.List.AddBefore(node, compareOp); + node.List.AddBefore(node, selectOp); + + result = selection; + } + } + + operation.TurnIntoCopy(result); + } + private static LinkedListNode<INode> RewriteGlobalAccess(LinkedListNode<INode> node, ShaderConfig config) { Operation operation = (Operation)node.Value; @@ -90,6 +173,15 @@ namespace Ryujinx.Graphics.Shader.Translation return local; } + Operand PrependStorageOperation(Instruction inst, StorageKind storageKind, params Operand[] sources) + { + Operand local = Local(); + + node.List.AddBefore(node, new Operation(inst, storageKind, local, sources)); + + return local; + } + Operand PrependExistingOperation(Operation operation) { Operand local = Local(); @@ -204,8 +296,6 @@ namespace Ryujinx.Graphics.Shader.Translation cbeUseMask &= ~(1 << slot); - config.SetUsedConstantBuffer(cbSlot); - Operand previousResult = PrependExistingOperation(storageOp); int cbOffset = GetConstantUbeOffset(slot); @@ -216,18 +306,17 @@ namespace Ryujinx.Graphics.Shader.Translation Operand byteOffsetConst = PrependOperation(Instruction.Subtract, addrLow, baseAddrTruncConst); Operand cbIndex = PrependOperation(Instruction.ShiftRightU32, byteOffsetConst, Const(2)); + Operand vecIndex = PrependOperation(Instruction.ShiftRightU32, cbIndex, Const(2)); + Operand elemIndex = PrependOperation(Instruction.BitwiseAnd, cbIndex, Const(3)); - Operand[] sourcesCb = new Operand[operation.SourcesCount]; + Operand[] sourcesCb = new Operand[4]; - sourcesCb[0] = Const(cbSlot); - sourcesCb[1] = cbIndex; - - for (int index = 2; index < operation.SourcesCount; index++) - { - sourcesCb[index] = operation.GetSource(index); - } + sourcesCb[0] = Const(config.ResourceManager.GetConstantBufferBinding(cbSlot)); + sourcesCb[1] = Const(0); + sourcesCb[2] = vecIndex; + sourcesCb[3] = elemIndex; - Operand ldcResult = PrependOperation(Instruction.LoadConstant, sourcesCb); + Operand ldcResult = PrependStorageOperation(Instruction.Load, StorageKind.ConstantBuffer, sourcesCb); storageOp = new Operation(Instruction.ConditionalSelect, operation.Dest, inRange, ldcResult, previousResult); } diff --git a/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs index ae60bcc6..77560797 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs @@ -39,6 +39,10 @@ namespace Ryujinx.Graphics.Shader.Translation public TranslationOptions Options { get; } + public ShaderProperties Properties { get; } + + public ResourceManager ResourceManager { get; } + public bool TransformFeedbackEnabled { get; } private TransformFeedbackOutput[] _transformFeedbackOutputs; @@ -109,7 +113,6 @@ namespace Ryujinx.Graphics.Shader.Translation public int AccessibleStorageBuffersMask { get; private set; } public int AccessibleConstantBuffersMask { get; private set; } - private int _usedConstantBuffers; private int _usedStorageBuffers; private int _usedStorageBuffersWrite; @@ -128,20 +131,17 @@ namespace Ryujinx.Graphics.Shader.Translation private readonly Dictionary<int, int> _sbSlots; private readonly Dictionary<int, int> _sbSlotsReverse; - private BufferDescriptor[] _cachedConstantBufferDescriptors; private BufferDescriptor[] _cachedStorageBufferDescriptors; private TextureDescriptor[] _cachedTextureDescriptors; private TextureDescriptor[] _cachedImageDescriptors; - private int _firstConstantBufferBinding; private int _firstStorageBufferBinding; - public int FirstConstantBufferBinding => _firstConstantBufferBinding; public int FirstStorageBufferBinding => _firstStorageBufferBinding; - public ShaderConfig(IGpuAccessor gpuAccessor, TranslationOptions options) + public ShaderConfig(ShaderStage stage, IGpuAccessor gpuAccessor, TranslationOptions options) { - Stage = ShaderStage.Compute; + Stage = stage; GpuAccessor = gpuAccessor; Options = options; @@ -158,6 +158,9 @@ namespace Ryujinx.Graphics.Shader.Translation _sbSlots = new Dictionary<int, int>(); _sbSlotsReverse = new Dictionary<int, int>(); + + Properties = new ShaderProperties(); + ResourceManager = new ResourceManager(stage, gpuAccessor, Properties); } public ShaderConfig( @@ -165,9 +168,8 @@ namespace Ryujinx.Graphics.Shader.Translation OutputTopology outputTopology, int maxOutputVertices, IGpuAccessor gpuAccessor, - TranslationOptions options) : this(gpuAccessor, options) + TranslationOptions options) : this(stage, gpuAccessor, options) { - Stage = stage; ThreadsPerInputPrimitive = 1; OutputTopology = outputTopology; MaxOutputVertices = maxOutputVertices; @@ -179,9 +181,8 @@ namespace Ryujinx.Graphics.Shader.Translation } } - public ShaderConfig(ShaderHeader header, IGpuAccessor gpuAccessor, TranslationOptions options) : this(gpuAccessor, options) + public ShaderConfig(ShaderHeader header, IGpuAccessor gpuAccessor, TranslationOptions options) : this(header.Stage, gpuAccessor, options) { - Stage = header.Stage; GpPassthrough = header.Stage == ShaderStage.Geometry && header.GpPassthrough; ThreadsPerInputPrimitive = header.ThreadsPerInputPrimitive; OutputTopology = header.OutputTopology; @@ -428,12 +429,13 @@ namespace Ryujinx.Graphics.Shader.Translation public void InheritFrom(ShaderConfig other) { + ResourceManager.InheritFrom(other.ResourceManager); + ClipDistancesWritten |= other.ClipDistancesWritten; UsedFeatures |= other.UsedFeatures; UsedInputAttributes |= other.UsedInputAttributes; UsedOutputAttributes |= other.UsedOutputAttributes; - _usedConstantBuffers |= other._usedConstantBuffers; _usedStorageBuffers |= other._usedStorageBuffers; _usedStorageBuffersWrite |= other._usedStorageBuffersWrite; @@ -641,11 +643,6 @@ namespace Ryujinx.Graphics.Shader.Translation AccessibleConstantBuffersMask = ubeMask; } - public void SetUsedConstantBuffer(int slot) - { - _usedConstantBuffers |= 1 << slot; - } - public void SetUsedStorageBuffer(int slot, bool write) { int mask = 1 << slot; @@ -762,27 +759,6 @@ namespace Ryujinx.Graphics.Shader.Translation return meta; } - public BufferDescriptor[] GetConstantBufferDescriptors() - { - if (_cachedConstantBufferDescriptors != null) - { - return _cachedConstantBufferDescriptors; - } - - int usedMask = _usedConstantBuffers; - - if (UsedFeatures.HasFlag(FeatureFlags.CbIndexing)) - { - usedMask |= (int)GpuAccessor.QueryConstantBufferUse(); - } - - return _cachedConstantBufferDescriptors = GetUniformBufferDescriptors( - usedMask, - UsedFeatures.HasFlag(FeatureFlags.CbIndexing), - out _firstConstantBufferBinding, - GpuAccessor.QueryBindingConstantBuffer); - } - public BufferDescriptor[] GetStorageBufferDescriptors() { if (_cachedStorageBufferDescriptors != null) @@ -798,47 +774,6 @@ namespace Ryujinx.Graphics.Shader.Translation GpuAccessor.QueryBindingStorageBuffer); } - private static BufferDescriptor[] GetUniformBufferDescriptors(int usedMask, bool isArray, out int firstBinding, Func<int, int> getBindingCallback) - { - firstBinding = 0; - int lastSlot = -1; - bool hasFirstBinding = false; - var descriptors = new BufferDescriptor[BitOperations.PopCount((uint)usedMask)]; - - for (int i = 0; i < descriptors.Length; i++) - { - int slot = BitOperations.TrailingZeroCount(usedMask); - - if (isArray) - { - // The next array entries also consumes bindings, even if they are unused. - for (int j = lastSlot + 1; j < slot; j++) - { - int binding = getBindingCallback(j); - - if (!hasFirstBinding) - { - firstBinding = binding; - hasFirstBinding = true; - } - } - } - - lastSlot = slot; - descriptors[i] = new BufferDescriptor(getBindingCallback(slot), slot); - - if (!hasFirstBinding) - { - firstBinding = descriptors[i].Binding; - hasFirstBinding = true; - } - - usedMask &= ~(1 << slot); - } - - return descriptors; - } - private BufferDescriptor[] GetStorageBufferDescriptors( int usedMask, int writtenMask, @@ -1009,7 +944,7 @@ namespace Ryujinx.Graphics.Shader.Translation public ShaderProgramInfo CreateProgramInfo(ShaderIdentification identification = ShaderIdentification.None) { return new ShaderProgramInfo( - GetConstantBufferDescriptors(), + ResourceManager.GetConstantBufferDescriptors(), GetStorageBufferDescriptors(), GetTextureDescriptors(), GetImageDescriptors(), diff --git a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs index 77d3b568..87d97e52 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -99,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.Translation if (options.Flags.HasFlag(TranslationFlags.Compute)) { - config = new ShaderConfig(gpuAccessor, options); + config = new ShaderConfig(ShaderStage.Compute, gpuAccessor, options); program = Decoder.Decode(config, address); } |