Delete ShaderConfig and organize shader resources/definitions better (#5509)
* Move some properties out of ShaderConfig * Stop using ShaderConfig on backends * Replace ShaderConfig usages on Translator and passes * Move remaining properties out of ShaderConfig and delete ShaderConfig * Remove ResourceManager property from TranslatorContext * Move Rewriter passes to separate transform pass files * Fix TransformPasses.RunPass on cases where a node is removed * Move remaining ClipDistancePrimitivesWritten and UsedFeatures updates to decode stage * Reduce excessive parameter passing a bit by using structs more * Remove binding parameter from ShaderProperties methods since it is redundant * Replace decoder instruction checks with switch statement * Put GLSL on the same plan as SPIR-V for input/output declaration * Stop mutating TranslatorContext state when Translate is called * Pass most of the graphics state using a struct instead of individual query methods * Auto-format * Auto-format * Add backend logging interface * Auto-format * Remove unnecessary use of interpolated strings * Remove more modifications of AttributeUsage after decode * PR feedback * gl_Layer is not supported on compute
This commit is contained in:
parent
8edfb2bc7b
commit
b423197619
68 changed files with 2653 additions and 2407 deletions
|
@ -1,3 +1,4 @@
|
|||
using Ryujinx.Graphics.Shader.Translation;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
@ -11,11 +12,26 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||
private readonly List<DecodedFunction> _functionsWithId;
|
||||
public int FunctionsWithIdCount => _functionsWithId.Count;
|
||||
|
||||
public DecodedProgram(DecodedFunction mainFunction, IReadOnlyDictionary<ulong, DecodedFunction> functions)
|
||||
public AttributeUsage AttributeUsage { get; }
|
||||
public FeatureFlags UsedFeatures { get; }
|
||||
public byte ClipDistancesWritten { get; }
|
||||
public int Cb1DataSize { get; }
|
||||
|
||||
public DecodedProgram(
|
||||
DecodedFunction mainFunction,
|
||||
IReadOnlyDictionary<ulong, DecodedFunction> functions,
|
||||
AttributeUsage attributeUsage,
|
||||
FeatureFlags usedFeatures,
|
||||
byte clipDistancesWritten,
|
||||
int cb1DataSize)
|
||||
{
|
||||
MainFunction = mainFunction;
|
||||
_functions = functions;
|
||||
_functionsWithId = new List<DecodedFunction>();
|
||||
_functionsWithId = new();
|
||||
AttributeUsage = attributeUsage;
|
||||
UsedFeatures = usedFeatures;
|
||||
ClipDistancesWritten = clipDistancesWritten;
|
||||
Cb1DataSize = cb1DataSize;
|
||||
}
|
||||
|
||||
public DecodedFunction GetFunctionByAddress(ulong address)
|
||||
|
|
|
@ -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)
|
||||
switch (op.Name)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue