| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- 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; private set; }
- 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 bool HalvePrimitiveId => _graphicsState.HalvePrimitiveId;
- 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 SupportsScaledVertexFormats { 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, ulong transformFeedbackVecMap, TransformFeedbackOutput[] transformFeedbackOutputs)
- {
- Stage = stage;
- TransformFeedbackEnabled = transformFeedbackOutputs != null;
- _transformFeedbackOutputs = transformFeedbackOutputs;
- _transformFeedbackDefinitions = new();
- PopulateTransformFeedbackDefinitions(transformFeedbackVecMap, transformFeedbackOutputs);
- }
- 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 supportsScaledVertexFormats,
- ulong transformFeedbackVecMap,
- TransformFeedbackOutput[] transformFeedbackOutputs)
- {
- Stage = stage;
- _graphicsState = graphicsState;
- GpPassthrough = gpPassthrough;
- ThreadsPerInputPrimitive = threadsPerInputPrimitive;
- OutputTopology = outputTopology;
- MaxOutputVertices = gpPassthrough ? graphicsState.Topology.ToInputVerticesNoAdjacency() : maxOutputVertices;
- ImapTypes = imapTypes;
- OmapTargets = omapTargets;
- OmapSampleMask = omapSampleMask;
- OmapDepth = omapDepth;
- LastInVertexPipeline = stage < ShaderStage.Fragment;
- SupportsScaledVertexFormats = supportsScaledVertexFormats;
- TransformFeedbackEnabled = transformFeedbackOutputs != null;
- _transformFeedbackOutputs = transformFeedbackOutputs;
- _transformFeedbackDefinitions = new();
- PopulateTransformFeedbackDefinitions(transformFeedbackVecMap, transformFeedbackOutputs);
- }
- private void PopulateTransformFeedbackDefinitions(ulong transformFeedbackVecMap, TransformFeedbackOutput[] transformFeedbackOutputs)
- {
- 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;
- }
- TransformFeedbackVariable transformFeedbackVariable = new(ioVariable, location, component);
- _transformFeedbackDefinitions.TryAdd(transformFeedbackVariable, transformFeedbackOutputs[wordOffset]);
- }
- }
- transformFeedbackVecMap &= ~(1UL << vecIndex);
- }
- }
- public void EnableInputIndexing()
- {
- IaIndexing = true;
- }
- public void EnableOutputIndexing()
- {
- OaIndexing = true;
- }
- public bool TryGetTransformFeedbackOutput(IoVariable ioVariable, int location, int component, out TransformFeedbackOutput transformFeedbackOutput)
- {
- if (!HasTransformFeedbackOutputs())
- {
- transformFeedbackOutput = default;
- return false;
- }
- TransformFeedbackVariable transformFeedbackVariable = new(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 TransformFeedbackOutput prev = ref _transformFeedbackOutputs[baseIndex + count - 1];
- ref TransformFeedbackOutput 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(SupportsScaledVertexFormats);
- }
- else
- {
- type |= AggregateType.FP32;
- }
- return type;
- }
- public AttributeType GetAttributeType(int location)
- {
- return _graphicsState.AttributeTypes[location];
- }
- public bool IsAttributeSint(int location)
- {
- return (_graphicsState.AttributeTypes[location] & ~AttributeType.AnyPacked) == AttributeType.Sint;
- }
- public bool IsAttributePacked(int location)
- {
- return _graphicsState.AttributeTypes[location].HasFlag(AttributeType.Packed);
- }
- public bool IsAttributePackedRgb10A2Signed(int location)
- {
- return _graphicsState.AttributeTypes[location].HasFlag(AttributeType.PackedRgb10A2Signed);
- }
- public int GetGeometryOutputIndexBufferStridePerInstance()
- {
- return MaxOutputVertices + OutputTopology switch
- {
- OutputTopology.LineStrip => MaxOutputVertices / 2,
- OutputTopology.TriangleStrip => MaxOutputVertices / 3,
- _ => MaxOutputVertices,
- };
- }
- public int GetGeometryOutputIndexBufferStride()
- {
- return GetGeometryOutputIndexBufferStridePerInstance() * ThreadsPerInputPrimitive;
- }
- }
- }
|