aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs')
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs639
1 files changed, 0 insertions, 639 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
deleted file mode 100644
index 27b46867..00000000
--- a/src/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ /dev/null
@@ -1,639 +0,0 @@
-using Ryujinx.Graphics.Shader.IntermediateRepresentation;
-using Ryujinx.Graphics.Shader.StructuredIr;
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-
-namespace Ryujinx.Graphics.Shader.Translation
-{
- class ShaderConfig
- {
- private const int ThreadsPerWarp = 32;
-
- public ShaderStage Stage { get; }
-
- public bool GpPassthrough { get; }
- public bool LastInVertexPipeline { get; private set; }
-
- public bool HasLayerInputAttribute { get; private set; }
- public int GpLayerInputAttribute { get; private set; }
- public int ThreadsPerInputPrimitive { get; }
-
- public OutputTopology OutputTopology { get; }
-
- public int MaxOutputVertices { get; }
-
- public int LocalMemorySize { get; }
-
- public ImapPixelType[] ImapTypes { get; }
-
- public int OmapTargets { get; }
- public bool OmapSampleMask { get; }
- public bool OmapDepth { get; }
-
- public IGpuAccessor GpuAccessor { get; }
-
- public TranslationOptions Options { get; }
-
- public ShaderProperties Properties => ResourceManager.Properties;
-
- public ResourceManager ResourceManager { get; set; }
-
- public bool TransformFeedbackEnabled { get; }
-
- private 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 int Size { get; private set; }
-
- public byte ClipDistancesWritten { get; private set; }
-
- public FeatureFlags UsedFeatures { get; private set; }
-
- public int Cb1DataSize { get; private set; }
-
- public bool LayerOutputWritten { get; private set; }
- public int LayerOutputAttribute { get; private set; }
-
- public bool NextUsesFixedFuncAttributes { get; private set; }
- public int UsedInputAttributes { get; private set; }
- public int UsedOutputAttributes { get; private set; }
- public HashSet<int> UsedInputAttributesPerPatch { get; }
- public HashSet<int> UsedOutputAttributesPerPatch { get; }
- public HashSet<int> NextUsedInputAttributesPerPatch { get; private set; }
- public int PassthroughAttributes { get; private set; }
- private int _nextUsedInputAttributes;
- private int _thisUsedInputAttributes;
- private Dictionary<int, int> _perPatchAttributeLocations;
-
- public UInt128 NextInputAttributesComponents { get; private set; }
- public UInt128 ThisInputAttributesComponents { get; private set; }
-
- public ShaderConfig(ShaderStage stage, IGpuAccessor gpuAccessor, TranslationOptions options, int localMemorySize)
- {
- Stage = stage;
- GpuAccessor = gpuAccessor;
- Options = options;
- LocalMemorySize = localMemorySize;
-
- _transformFeedbackDefinitions = new Dictionary<TransformFeedbackVariable, TransformFeedbackOutput>();
-
- TransformFeedbackEnabled =
- stage != ShaderStage.Compute &&
- gpuAccessor.QueryTransformFeedbackEnabled() &&
- gpuAccessor.QueryHostSupportsTransformFeedback();
-
- UsedInputAttributesPerPatch = new HashSet<int>();
- UsedOutputAttributesPerPatch = new HashSet<int>();
-
- ShaderProperties properties;
-
- switch (stage)
- {
- case ShaderStage.Fragment:
- bool originUpperLeft = options.TargetApi == TargetApi.Vulkan || gpuAccessor.QueryYNegateEnabled();
- properties = new ShaderProperties(originUpperLeft);
- break;
- default:
- properties = new ShaderProperties();
- break;
- }
-
- ResourceManager = new ResourceManager(stage, gpuAccessor, properties);
-
- if (!gpuAccessor.QueryHostSupportsTransformFeedback() && gpuAccessor.QueryTransformFeedbackEnabled())
- {
- StructureType tfeInfoStruct = new(new StructureField[]
- {
- new(AggregateType.Array | AggregateType.U32, "base_offset", 4),
- new(AggregateType.U32, "vertex_count"),
- });
-
- BufferDefinition tfeInfoBuffer = new(BufferLayout.Std430, 1, Constants.TfeInfoBinding, "tfe_info", tfeInfoStruct);
-
- properties.AddOrUpdateStorageBuffer(Constants.TfeInfoBinding, tfeInfoBuffer);
-
- StructureType tfeDataStruct = new(new StructureField[]
- {
- new(AggregateType.Array | AggregateType.U32, "data", 0),
- });
-
- for (int i = 0; i < Constants.TfeBuffersCount; i++)
- {
- int binding = Constants.TfeBufferBaseBinding + i;
- BufferDefinition tfeDataBuffer = new(BufferLayout.Std430, 1, binding, $"tfe_data{i}", tfeDataStruct);
- properties.AddOrUpdateStorageBuffer(binding, tfeDataBuffer);
- }
- }
- }
-
- public ShaderConfig(
- ShaderStage stage,
- OutputTopology outputTopology,
- int maxOutputVertices,
- IGpuAccessor gpuAccessor,
- TranslationOptions options) : this(stage, gpuAccessor, options, 0)
- {
- ThreadsPerInputPrimitive = 1;
- OutputTopology = outputTopology;
- MaxOutputVertices = maxOutputVertices;
- }
-
- public ShaderConfig(
- ShaderHeader header,
- IGpuAccessor gpuAccessor,
- TranslationOptions options) : this(header.Stage, gpuAccessor, options, GetLocalMemorySize(header))
- {
- GpPassthrough = header.Stage == ShaderStage.Geometry && header.GpPassthrough;
- ThreadsPerInputPrimitive = header.ThreadsPerInputPrimitive;
- OutputTopology = header.OutputTopology;
- MaxOutputVertices = header.MaxOutputVertexCount;
- ImapTypes = header.ImapTypes;
- OmapTargets = header.OmapTargets;
- OmapSampleMask = header.OmapSampleMask;
- OmapDepth = header.OmapDepth;
- LastInVertexPipeline = header.Stage < ShaderStage.Fragment;
- }
-
- private static int GetLocalMemorySize(ShaderHeader header)
- {
- return header.ShaderLocalMemoryLowSize + header.ShaderLocalMemoryHighSize + (header.ShaderLocalMemoryCrsSize / ThreadsPerWarp);
- }
-
- private void EnsureTransformFeedbackInitialized()
- {
- if (HasTransformFeedbackOutputs() && _transformFeedbackOutputs == null)
- {
- TransformFeedbackOutput[] transformFeedbackOutputs = new TransformFeedbackOutput[0xc0];
- ulong vecMap = 0UL;
-
- for (int tfbIndex = 0; tfbIndex < 4; tfbIndex++)
- {
- var locations = GpuAccessor.QueryTransformFeedbackVaryingLocations(tfbIndex);
- var stride = GpuAccessor.QueryTransformFeedbackStride(tfbIndex);
-
- for (int i = 0; i < locations.Length; i++)
- {
- byte wordOffset = locations[i];
- if (wordOffset < 0xc0)
- {
- transformFeedbackOutputs[wordOffset] = new TransformFeedbackOutput(tfbIndex, i * 4, stride);
- vecMap |= 1UL << (wordOffset / 4);
- }
- }
- }
-
- _transformFeedbackOutputs = transformFeedbackOutputs;
-
- while (vecMap != 0)
- {
- int vecIndex = BitOperations.TrailingZeroCount(vecMap);
-
- 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]);
- }
- }
-
- vecMap &= ~(1UL << vecIndex);
- }
- }
- }
-
- public TransformFeedbackOutput[] GetTransformFeedbackOutputs()
- {
- EnsureTransformFeedbackInitialized();
- return _transformFeedbackOutputs;
- }
-
- public bool TryGetTransformFeedbackOutput(IoVariable ioVariable, int location, int component, out TransformFeedbackOutput transformFeedbackOutput)
- {
- EnsureTransformFeedbackInitialized();
- 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 && !UsedFeatures.HasFlag(FeatureFlags.IaIndexing)) ||
- (isOutput && !UsedFeatures.HasFlag(FeatureFlags.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)
- {
- EnsureTransformFeedbackInitialized();
-
- 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)
- {
- EnsureTransformFeedbackInitialized();
-
- 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 | GpuAccessor.QueryFragmentOutputType(location).ToAggregateType();
- }
-
- public AggregateType GetUserDefinedType(int location, bool isOutput)
- {
- if ((!isOutput && UsedFeatures.HasFlag(FeatureFlags.IaIndexing)) ||
- (isOutput && UsedFeatures.HasFlag(FeatureFlags.OaIndexing)))
- {
- return AggregateType.Array | AggregateType.Vector4 | AggregateType.FP32;
- }
-
- AggregateType type = AggregateType.Vector4;
-
- if (Stage == ShaderStage.Vertex && !isOutput)
- {
- type |= GpuAccessor.QueryAttributeType(location).ToAggregateType();
- }
- else
- {
- type |= AggregateType.FP32;
- }
-
- return type;
- }
-
- public int GetDepthRegister()
- {
- // The depth register is always two registers after the last color output.
- return BitOperations.PopCount((uint)OmapTargets) + 1;
- }
-
- public uint ConstantBuffer1Read(int offset)
- {
- if (Cb1DataSize < offset + 4)
- {
- Cb1DataSize = offset + 4;
- }
-
- return GpuAccessor.ConstantBuffer1Read(offset);
- }
-
- public TextureFormat GetTextureFormat(int handle, int cbufSlot = -1)
- {
- // When the formatted load extension is supported, we don't need to
- // specify a format, we can just declare it without a format and the GPU will handle it.
- if (GpuAccessor.QueryHostSupportsImageLoadFormatted())
- {
- return TextureFormat.Unknown;
- }
-
- var format = GpuAccessor.QueryTextureFormat(handle, cbufSlot);
-
- if (format == TextureFormat.Unknown)
- {
- GpuAccessor.Log($"Unknown format for texture {handle}.");
-
- format = TextureFormat.R8G8B8A8Unorm;
- }
-
- return format;
- }
-
- private static bool FormatSupportsAtomic(TextureFormat format)
- {
- return format == TextureFormat.R32Sint || format == TextureFormat.R32Uint;
- }
-
- public TextureFormat GetTextureFormatAtomic(int handle, int cbufSlot = -1)
- {
- // Atomic image instructions do not support GL_EXT_shader_image_load_formatted,
- // and must have a type specified. Default to R32Sint if not available.
-
- var format = GpuAccessor.QueryTextureFormat(handle, cbufSlot);
-
- if (!FormatSupportsAtomic(format))
- {
- GpuAccessor.Log($"Unsupported format for texture {handle}: {format}.");
-
- format = TextureFormat.R32Sint;
- }
-
- return format;
- }
-
- public void SizeAdd(int size)
- {
- Size += size;
- }
-
- public void InheritFrom(ShaderConfig other)
- {
- ClipDistancesWritten |= other.ClipDistancesWritten;
- UsedFeatures |= other.UsedFeatures;
-
- UsedInputAttributes |= other.UsedInputAttributes;
- UsedOutputAttributes |= other.UsedOutputAttributes;
- }
-
- public void SetLayerOutputAttribute(int attr)
- {
- LayerOutputWritten = true;
- LayerOutputAttribute = attr;
- }
-
- public void SetGeometryShaderLayerInputAttribute(int attr)
- {
- HasLayerInputAttribute = true;
- GpLayerInputAttribute = attr;
- }
-
- public void SetLastInVertexPipeline()
- {
- LastInVertexPipeline = true;
- }
-
- public void SetInputUserAttributeFixedFunc(int index)
- {
- UsedInputAttributes |= 1 << index;
- }
-
- public void SetOutputUserAttributeFixedFunc(int index)
- {
- UsedOutputAttributes |= 1 << index;
- }
-
- public void SetInputUserAttribute(int index, int component)
- {
- int mask = 1 << index;
-
- UsedInputAttributes |= mask;
- _thisUsedInputAttributes |= mask;
- ThisInputAttributesComponents |= UInt128.One << (index * 4 + component);
- }
-
- public void SetInputUserAttributePerPatch(int index)
- {
- UsedInputAttributesPerPatch.Add(index);
- }
-
- public void SetOutputUserAttribute(int index)
- {
- UsedOutputAttributes |= 1 << index;
- }
-
- public void SetOutputUserAttributePerPatch(int index)
- {
- UsedOutputAttributesPerPatch.Add(index);
- }
-
- public void MergeFromtNextStage(ShaderConfig config)
- {
- NextInputAttributesComponents = config.ThisInputAttributesComponents;
- NextUsedInputAttributesPerPatch = config.UsedInputAttributesPerPatch;
- NextUsesFixedFuncAttributes = config.UsedFeatures.HasFlag(FeatureFlags.FixedFuncAttr);
- MergeOutputUserAttributes(config.UsedInputAttributes, config.UsedInputAttributesPerPatch);
-
- if (UsedOutputAttributesPerPatch.Count != 0)
- {
- // Regular and per-patch input/output locations can't overlap,
- // so we must assign on our location using unused regular input/output locations.
-
- Dictionary<int, int> locationsMap = new();
-
- int freeMask = ~UsedOutputAttributes;
-
- foreach (int attr in UsedOutputAttributesPerPatch)
- {
- int location = BitOperations.TrailingZeroCount(freeMask);
- if (location == 32)
- {
- config.GpuAccessor.Log($"No enough free locations for patch input/output 0x{attr:X}.");
- break;
- }
-
- locationsMap.Add(attr, location);
- freeMask &= ~(1 << location);
- }
-
- // Both stages must agree on the locations, so use the same "map" for both.
- _perPatchAttributeLocations = locationsMap;
- config._perPatchAttributeLocations = locationsMap;
- }
-
- // We don't consider geometry shaders using the geometry shader passthrough feature
- // as being the last because when this feature is used, it can't actually modify any of the outputs,
- // so the stage that comes before it is the last one that can do modifications.
- if (config.Stage != ShaderStage.Fragment && (config.Stage != ShaderStage.Geometry || !config.GpPassthrough))
- {
- LastInVertexPipeline = false;
- }
- }
-
- public void MergeOutputUserAttributes(int mask, IEnumerable<int> perPatch)
- {
- _nextUsedInputAttributes = mask;
-
- if (GpPassthrough)
- {
- PassthroughAttributes = mask & ~UsedOutputAttributes;
- }
- else
- {
- UsedOutputAttributes |= mask;
- UsedOutputAttributesPerPatch.UnionWith(perPatch);
- }
- }
-
- public int GetPerPatchAttributeLocation(int index)
- {
- if (_perPatchAttributeLocations == null || !_perPatchAttributeLocations.TryGetValue(index, out int location))
- {
- return index;
- }
-
- return location;
- }
-
- public bool IsUsedOutputAttribute(int attr)
- {
- // The check for fixed function attributes on the next stage is conservative,
- // returning false if the output is just not used by the next stage is also valid.
- if (NextUsesFixedFuncAttributes &&
- attr >= AttributeConsts.UserAttributeBase &&
- attr < AttributeConsts.UserAttributeEnd)
- {
- int index = (attr - AttributeConsts.UserAttributeBase) >> 4;
- return (_nextUsedInputAttributes & (1 << index)) != 0;
- }
-
- return true;
- }
-
- public int GetFreeUserAttribute(bool isOutput, int index)
- {
- int useMask = isOutput ? _nextUsedInputAttributes : _thisUsedInputAttributes;
- int bit = -1;
-
- while (useMask != -1)
- {
- bit = BitOperations.TrailingZeroCount(~useMask);
-
- if (bit == 32)
- {
- bit = -1;
- break;
- }
- else if (index < 1)
- {
- break;
- }
-
- useMask |= 1 << bit;
- index--;
- }
-
- return bit;
- }
-
- public void SetAllInputUserAttributes()
- {
- UsedInputAttributes |= Constants.AllAttributesMask;
- ThisInputAttributesComponents |= ~UInt128.Zero >> (128 - Constants.MaxAttributes * 4);
- }
-
- public void SetAllOutputUserAttributes()
- {
- UsedOutputAttributes |= Constants.AllAttributesMask;
- }
-
- public void SetClipDistanceWritten(int index)
- {
- ClipDistancesWritten |= (byte)(1 << index);
- }
-
- public void SetUsedFeature(FeatureFlags flags)
- {
- UsedFeatures |= flags;
- }
-
- public ShaderProgramInfo CreateProgramInfo(ShaderIdentification identification = ShaderIdentification.None)
- {
- return new ShaderProgramInfo(
- ResourceManager.GetConstantBufferDescriptors(),
- ResourceManager.GetStorageBufferDescriptors(),
- ResourceManager.GetTextureDescriptors(),
- ResourceManager.GetImageDescriptors(),
- identification,
- GpLayerInputAttribute,
- Stage,
- UsedFeatures.HasFlag(FeatureFlags.FragCoordXY),
- UsedFeatures.HasFlag(FeatureFlags.InstanceId),
- UsedFeatures.HasFlag(FeatureFlags.DrawParameters),
- UsedFeatures.HasFlag(FeatureFlags.RtLayer),
- ClipDistancesWritten,
- OmapTargets);
- }
- }
-}