1
1
mirror of https://github.com/ryujinx-mirror/ryujinx.git synced 2025-02-05 06:22:56 -06:00
gdkchan b423197619
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
2023-08-13 22:26:42 -03:00

316 lines
11 KiB
C#

using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using System;
using System.Collections.Generic;
using System.Numerics;
namespace Ryujinx.Graphics.Shader.Translation
{
class ShaderDefinitions
{
private readonly GpuGraphicsState _graphicsState;
public ShaderStage Stage { get; }
public int ComputeLocalSizeX { get; }
public int ComputeLocalSizeY { get; }
public int ComputeLocalSizeZ { get; }
public bool TessCw => _graphicsState.TessCw;
public TessPatchType TessPatchType => _graphicsState.TessPatchType;
public TessSpacing TessSpacing => _graphicsState.TessSpacing;
public bool AlphaToCoverageDitherEnable => _graphicsState.AlphaToCoverageEnable && _graphicsState.AlphaToCoverageDitherEnable;
public bool ViewportTransformDisable => _graphicsState.ViewportTransformDisable;
public bool DepthMode => _graphicsState.DepthMode;
public float PointSize => _graphicsState.PointSize;
public AlphaTestOp AlphaTestCompare => _graphicsState.AlphaTestCompare;
public float AlphaTestReference => _graphicsState.AlphaTestReference;
public bool GpPassthrough { get; }
public bool LastInVertexPipeline { get; set; }
public int ThreadsPerInputPrimitive { get; }
public InputTopology InputTopology => _graphicsState.Topology;
public OutputTopology OutputTopology { get; }
public int MaxOutputVertices { get; }
public bool DualSourceBlend => _graphicsState.DualSourceBlendEnable;
public bool EarlyZForce => _graphicsState.EarlyZForce;
public bool YNegateEnabled => _graphicsState.YNegateEnabled;
public bool OriginUpperLeft => _graphicsState.OriginUpperLeft;
public ImapPixelType[] ImapTypes { get; }
public bool IaIndexing { get; private set; }
public bool OaIndexing { get; private set; }
public int OmapTargets { get; }
public bool OmapSampleMask { get; }
public bool OmapDepth { get; }
public bool TransformFeedbackEnabled { get; }
private readonly TransformFeedbackOutput[] _transformFeedbackOutputs;
readonly struct TransformFeedbackVariable : IEquatable<TransformFeedbackVariable>
{
public IoVariable IoVariable { get; }
public int Location { get; }
public int Component { get; }
public TransformFeedbackVariable(IoVariable ioVariable, int location = 0, int component = 0)
{
IoVariable = ioVariable;
Location = location;
Component = component;
}
public override bool Equals(object other)
{
return other is TransformFeedbackVariable tfbVar && Equals(tfbVar);
}
public bool Equals(TransformFeedbackVariable other)
{
return IoVariable == other.IoVariable &&
Location == other.Location &&
Component == other.Component;
}
public override int GetHashCode()
{
return (int)IoVariable | (Location << 8) | (Component << 16);
}
public override string ToString()
{
return $"{IoVariable}.{Location}.{Component}";
}
}
private readonly Dictionary<TransformFeedbackVariable, TransformFeedbackOutput> _transformFeedbackDefinitions;
public ShaderDefinitions(ShaderStage stage)
{
Stage = stage;
}
public ShaderDefinitions(
ShaderStage stage,
int computeLocalSizeX,
int computeLocalSizeY,
int computeLocalSizeZ)
{
Stage = stage;
ComputeLocalSizeX = computeLocalSizeX;
ComputeLocalSizeY = computeLocalSizeY;
ComputeLocalSizeZ = computeLocalSizeZ;
}
public ShaderDefinitions(
ShaderStage stage,
GpuGraphicsState graphicsState,
bool gpPassthrough,
int threadsPerInputPrimitive,
OutputTopology outputTopology,
int maxOutputVertices)
{
Stage = stage;
_graphicsState = graphicsState;
GpPassthrough = gpPassthrough;
ThreadsPerInputPrimitive = threadsPerInputPrimitive;
OutputTopology = outputTopology;
MaxOutputVertices = maxOutputVertices;
}
public ShaderDefinitions(
ShaderStage stage,
GpuGraphicsState graphicsState,
bool gpPassthrough,
int threadsPerInputPrimitive,
OutputTopology outputTopology,
int maxOutputVertices,
ImapPixelType[] imapTypes,
int omapTargets,
bool omapSampleMask,
bool omapDepth,
bool transformFeedbackEnabled,
ulong transformFeedbackVecMap,
TransformFeedbackOutput[] transformFeedbackOutputs)
{
Stage = stage;
_graphicsState = graphicsState;
GpPassthrough = gpPassthrough;
ThreadsPerInputPrimitive = threadsPerInputPrimitive;
OutputTopology = outputTopology;
MaxOutputVertices = maxOutputVertices;
ImapTypes = imapTypes;
OmapTargets = omapTargets;
OmapSampleMask = omapSampleMask;
OmapDepth = omapDepth;
LastInVertexPipeline = stage < ShaderStage.Fragment;
TransformFeedbackEnabled = transformFeedbackEnabled;
_transformFeedbackOutputs = transformFeedbackOutputs;
_transformFeedbackDefinitions = new();
while (transformFeedbackVecMap != 0)
{
int vecIndex = BitOperations.TrailingZeroCount(transformFeedbackVecMap);
for (int subIndex = 0; subIndex < 4; subIndex++)
{
int wordOffset = vecIndex * 4 + subIndex;
int byteOffset = wordOffset * 4;
if (transformFeedbackOutputs[wordOffset].Valid)
{
IoVariable ioVariable = Instructions.AttributeMap.GetIoVariable(this, byteOffset, out int location);
int component = 0;
if (HasPerLocationInputOrOutputComponent(ioVariable, location, subIndex, isOutput: true))
{
component = subIndex;
}
var transformFeedbackVariable = new TransformFeedbackVariable(ioVariable, location, component);
_transformFeedbackDefinitions.TryAdd(transformFeedbackVariable, transformFeedbackOutputs[wordOffset]);
}
}
transformFeedbackVecMap &= ~(1UL << vecIndex);
}
}
public void EnableInputIndexing()
{
IaIndexing = true;
}
public void EnableOutputIndexing()
{
OaIndexing = true;
}
public TransformFeedbackOutput[] GetTransformFeedbackOutputs()
{
if (!HasTransformFeedbackOutputs())
{
return null;
}
return _transformFeedbackOutputs;
}
public bool TryGetTransformFeedbackOutput(IoVariable ioVariable, int location, int component, out TransformFeedbackOutput transformFeedbackOutput)
{
if (!HasTransformFeedbackOutputs())
{
transformFeedbackOutput = default;
return false;
}
var transformFeedbackVariable = new TransformFeedbackVariable(ioVariable, location, component);
return _transformFeedbackDefinitions.TryGetValue(transformFeedbackVariable, out transformFeedbackOutput);
}
private bool HasTransformFeedbackOutputs()
{
return TransformFeedbackEnabled && (LastInVertexPipeline || Stage == ShaderStage.Fragment);
}
public bool HasTransformFeedbackOutputs(bool isOutput)
{
return TransformFeedbackEnabled && ((isOutput && LastInVertexPipeline) || (!isOutput && Stage == ShaderStage.Fragment));
}
public bool HasPerLocationInputOrOutput(IoVariable ioVariable, bool isOutput)
{
if (ioVariable == IoVariable.UserDefined)
{
return (!isOutput && !IaIndexing) || (isOutput && !OaIndexing);
}
return ioVariable == IoVariable.FragmentOutputColor;
}
public bool HasPerLocationInputOrOutputComponent(IoVariable ioVariable, int location, int component, bool isOutput)
{
if (ioVariable != IoVariable.UserDefined || !HasTransformFeedbackOutputs(isOutput))
{
return false;
}
return GetTransformFeedbackOutputComponents(location, component) == 1;
}
public TransformFeedbackOutput GetTransformFeedbackOutput(int wordOffset)
{
return _transformFeedbackOutputs[wordOffset];
}
public TransformFeedbackOutput GetTransformFeedbackOutput(int location, int component)
{
return GetTransformFeedbackOutput((AttributeConsts.UserAttributeBase / 4) + location * 4 + component);
}
public int GetTransformFeedbackOutputComponents(int location, int component)
{
int baseIndex = (AttributeConsts.UserAttributeBase / 4) + location * 4;
int index = baseIndex + component;
int count = 1;
for (; count < 4; count++)
{
ref var prev = ref _transformFeedbackOutputs[baseIndex + count - 1];
ref var curr = ref _transformFeedbackOutputs[baseIndex + count];
int prevOffset = prev.Offset;
int currOffset = curr.Offset;
if (!prev.Valid || !curr.Valid || prevOffset + 4 != currOffset)
{
break;
}
}
if (baseIndex + count <= index)
{
return 1;
}
return count;
}
public AggregateType GetFragmentOutputColorType(int location)
{
return AggregateType.Vector4 | _graphicsState.FragmentOutputTypes[location].ToAggregateType();
}
public AggregateType GetUserDefinedType(int location, bool isOutput)
{
if ((!isOutput && IaIndexing) || (isOutput && OaIndexing))
{
return AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32;
}
AggregateType type = AggregateType.Vector4;
if (Stage == ShaderStage.Vertex && !isOutput)
{
type |= _graphicsState.AttributeTypes[location].ToAggregateType();
}
else
{
type |= AggregateType.FP32;
}
return type;
}
}
}