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:
gdkchan 2023-08-13 22:26:42 -03:00 committed by GitHub
parent 8edfb2bc7b
commit b423197619
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
68 changed files with 2653 additions and 2407 deletions

View file

@ -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)

View file

@ -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))