diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs | 172 |
1 files changed, 135 insertions, 37 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs index ba31c020..d18a9baf 100644 --- a/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs +++ b/src/Ryujinx.Graphics.Shader/Decoders/Decoder.cs @@ -9,8 +9,45 @@ namespace Ryujinx.Graphics.Shader.Decoders { static class Decoder { - public static DecodedProgram Decode(ShaderConfig config, ulong startAddress) + private class Context { + public AttributeUsage AttributeUsage { get; } + public FeatureFlags UsedFeatures { get; private set; } + public byte ClipDistancesWritten { get; private set; } + public int Cb1DataSize { get; private set; } + + private readonly IGpuAccessor _gpuAccessor; + + public Context(IGpuAccessor gpuAccessor) + { + _gpuAccessor = gpuAccessor; + AttributeUsage = new(gpuAccessor); + } + + public uint ConstantBuffer1Read(int offset) + { + if (Cb1DataSize < offset + 4) + { + Cb1DataSize = offset + 4; + } + + return _gpuAccessor.ConstantBuffer1Read(offset); + } + + public void SetUsedFeature(FeatureFlags flags) + { + UsedFeatures |= flags; + } + + public void SetClipDistanceWritten(int index) + { + ClipDistancesWritten |= (byte)(1 << index); + } + } + + public static DecodedProgram Decode(ShaderDefinitions definitions, IGpuAccessor gpuAccessor, ulong startAddress) + { + Context context = new(gpuAccessor); Queue<DecodedFunction> functionsQueue = new(); Dictionary<ulong, DecodedFunction> functionsVisited = new(); @@ -89,7 +126,7 @@ namespace Ryujinx.Graphics.Shader.Decoders } } - FillBlock(config, currBlock, limitAddress, startAddress); + FillBlock(definitions, gpuAccessor, context, currBlock, limitAddress, startAddress); if (currBlock.OpCodes.Count != 0) { @@ -148,7 +185,7 @@ namespace Ryujinx.Graphics.Shader.Decoders } // Try to find targets for BRX (indirect branch) instructions. - hasNewTarget = FindBrxTargets(config, blocks, GetBlock); + hasNewTarget = FindBrxTargets(context, blocks, GetBlock); // If we discovered new branch targets from the BRX instruction, // we need another round of decoding to decode the new blocks. @@ -160,7 +197,13 @@ namespace Ryujinx.Graphics.Shader.Decoders currentFunction.SetBlocks(blocks.ToArray()); } - return new DecodedProgram(mainFunction, functionsVisited); + return new DecodedProgram( + mainFunction, + functionsVisited, + context.AttributeUsage, + context.UsedFeatures, + context.ClipDistancesWritten, + context.Cb1DataSize); } private static bool BinarySearch(List<Block> blocks, ulong address, out int index) @@ -198,10 +241,14 @@ namespace Ryujinx.Graphics.Shader.Decoders return false; } - private static void FillBlock(ShaderConfig config, Block block, ulong limitAddress, ulong startAddress) + private static void FillBlock( + ShaderDefinitions definitions, + IGpuAccessor gpuAccessor, + Context context, + Block block, + ulong limitAddress, + ulong startAddress) { - IGpuAccessor gpuAccessor = config.GpuAccessor; - ulong address = block.Address; int bufferOffset = 0; ReadOnlySpan<ulong> buffer = ReadOnlySpan<ulong>.Empty; @@ -235,27 +282,31 @@ namespace Ryujinx.Graphics.Shader.Decoders if (op.Props.HasFlag(InstProps.TexB)) { - config.SetUsedFeature(FeatureFlags.Bindless); + context.SetUsedFeature(FeatureFlags.Bindless); } - if (op.Name == InstName.Ald || op.Name == InstName.Ast || op.Name == InstName.Ipa) - { - SetUserAttributeUses(config, op.Name, opCode); - } - else if (op.Name == InstName.Pbk || op.Name == InstName.Pcnt || op.Name == InstName.Ssy) - { - block.AddPushOp(op); - } - else if (op.Name == InstName.Ldl || op.Name == InstName.Stl) + switch (op.Name) { - config.SetUsedFeature(FeatureFlags.LocalMemory); - } - else if (op.Name == InstName.Atoms || - op.Name == InstName.AtomsCas || - op.Name == InstName.Lds || - op.Name == InstName.Sts) - { - config.SetUsedFeature(FeatureFlags.SharedMemory); + case InstName.Ald: + case InstName.Ast: + case InstName.Ipa: + SetUserAttributeUses(definitions, context, op.Name, opCode); + break; + case InstName.Pbk: + case InstName.Pcnt: + case InstName.Ssy: + block.AddPushOp(op); + break; + case InstName.Ldl: + case InstName.Stl: + context.SetUsedFeature(FeatureFlags.LocalMemory); + break; + case InstName.Atoms: + case InstName.AtomsCas: + case InstName.Lds: + case InstName.Sts: + context.SetUsedFeature(FeatureFlags.SharedMemory); + break; } block.OpCodes.Add(op); @@ -267,7 +318,7 @@ namespace Ryujinx.Graphics.Shader.Decoders block.EndAddress = address; } - private static void SetUserAttributeUses(ShaderConfig config, InstName name, ulong opCode) + private static void SetUserAttributeUses(ShaderDefinitions definitions, Context context, InstName name, ulong opCode) { int offset; int count = 1; @@ -304,13 +355,13 @@ namespace Ryujinx.Graphics.Shader.Decoders { if (isStore) { - config.SetAllOutputUserAttributes(); - config.SetUsedFeature(FeatureFlags.OaIndexing); + context.AttributeUsage.SetAllOutputUserAttributes(); + definitions.EnableOutputIndexing(); } else { - config.SetAllInputUserAttributes(); - config.SetUsedFeature(FeatureFlags.IaIndexing); + context.AttributeUsage.SetAllInputUserAttributes(); + definitions.EnableInputIndexing(); } } else @@ -328,11 +379,11 @@ namespace Ryujinx.Graphics.Shader.Decoders if (isStore) { - config.SetOutputUserAttributePerPatch(index); + context.AttributeUsage.SetOutputUserAttributePerPatch(index); } else { - config.SetInputUserAttributePerPatch(index); + context.AttributeUsage.SetInputUserAttributePerPatch(index); } } } @@ -343,11 +394,11 @@ namespace Ryujinx.Graphics.Shader.Decoders if (isStore) { - config.SetOutputUserAttribute(index); + context.AttributeUsage.SetOutputUserAttribute(index); } else { - config.SetInputUserAttribute(index, (userAttr >> 2) & 3); + context.AttributeUsage.SetInputUserAttribute(index, (userAttr >> 2) & 3); } } @@ -356,7 +407,54 @@ namespace Ryujinx.Graphics.Shader.Decoders (attr >= AttributeConsts.FrontColorDiffuseR && attr < AttributeConsts.ClipDistance0) || (attr >= AttributeConsts.TexCoordBase && attr < AttributeConsts.TexCoordEnd))) { - config.SetUsedFeature(FeatureFlags.FixedFuncAttr); + context.SetUsedFeature(FeatureFlags.FixedFuncAttr); + } + else + { + if (isStore) + { + switch (attr) + { + case AttributeConsts.Layer: + if (definitions.Stage != ShaderStage.Compute && definitions.Stage != ShaderStage.Fragment) + { + context.SetUsedFeature(FeatureFlags.RtLayer); + } + break; + case AttributeConsts.ClipDistance0: + case AttributeConsts.ClipDistance1: + case AttributeConsts.ClipDistance2: + case AttributeConsts.ClipDistance3: + case AttributeConsts.ClipDistance4: + case AttributeConsts.ClipDistance5: + case AttributeConsts.ClipDistance6: + case AttributeConsts.ClipDistance7: + if (definitions.Stage == ShaderStage.Vertex) + { + context.SetClipDistanceWritten((attr - AttributeConsts.ClipDistance0) / 4); + } + break; + } + } + else + { + switch (attr) + { + case AttributeConsts.PositionX: + case AttributeConsts.PositionY: + if (definitions.Stage == ShaderStage.Fragment) + { + context.SetUsedFeature(FeatureFlags.FragCoordXY); + } + break; + case AttributeConsts.InstanceId: + if (definitions.Stage == ShaderStage.Vertex) + { + context.SetUsedFeature(FeatureFlags.InstanceId); + } + break; + } + } } } } @@ -379,7 +477,7 @@ namespace Ryujinx.Graphics.Shader.Decoders return condOp.Pred == RegisterConsts.PredicateTrueIndex && !condOp.PredInv; } - private static bool FindBrxTargets(ShaderConfig config, IEnumerable<Block> blocks, Func<ulong, Block> getBlock) + private static bool FindBrxTargets(Context context, IEnumerable<Block> blocks, Func<ulong, Block> getBlock) { bool hasNewTarget = false; @@ -406,7 +504,7 @@ namespace Ryujinx.Graphics.Shader.Decoders for (int i = 0; i < cbOffsetsCount; i++) { - uint targetOffset = config.ConstantBuffer1Read(cbBaseOffset + i * 4); + uint targetOffset = context.ConstantBuffer1Read(cbBaseOffset + i * 4); ulong targetAddress = baseOffset + targetOffset; if (visited.Add(targetAddress)) |