aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/Translation/AttributeUsage.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-08-13 22:26:42 -0300
committerGitHub <noreply@github.com>2023-08-13 22:26:42 -0300
commitb423197619dd8d9dda1c255a76105bf30e255dae (patch)
treee3898b3b1672f022b5de4522b51bd21583043996 /src/Ryujinx.Graphics.Shader/Translation/AttributeUsage.cs
parent8edfb2bc7b8507d0ef51f0544eb32a65f0bf54a1 (diff)
Delete ShaderConfig and organize shader resources/definitions better (#5509)1.1.985
* 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
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/AttributeUsage.cs')
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/AttributeUsage.cs168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/AttributeUsage.cs b/src/Ryujinx.Graphics.Shader/Translation/AttributeUsage.cs
new file mode 100644
index 00000000..9dab9fdf
--- /dev/null
+++ b/src/Ryujinx.Graphics.Shader/Translation/AttributeUsage.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+
+namespace Ryujinx.Graphics.Shader.Translation
+{
+ class AttributeUsage
+ {
+ 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;
+ private readonly IGpuAccessor _gpuAccessor;
+
+ public UInt128 NextInputAttributesComponents { get; private set; }
+ public UInt128 ThisInputAttributesComponents { get; private set; }
+
+ public AttributeUsage(IGpuAccessor gpuAccessor)
+ {
+ _gpuAccessor = gpuAccessor;
+
+ UsedInputAttributesPerPatch = new();
+ UsedOutputAttributesPerPatch = new();
+ }
+
+ 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(bool gpPassthrough, bool nextUsesFixedFunctionAttributes, AttributeUsage nextStage)
+ {
+ NextInputAttributesComponents = nextStage.ThisInputAttributesComponents;
+ NextUsedInputAttributesPerPatch = nextStage.UsedInputAttributesPerPatch;
+ NextUsesFixedFuncAttributes = nextUsesFixedFunctionAttributes;
+ MergeOutputUserAttributes(gpPassthrough, nextStage.UsedInputAttributes, nextStage.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)
+ {
+ _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;
+ nextStage._perPatchAttributeLocations = locationsMap;
+ }
+ }
+
+ private void MergeOutputUserAttributes(bool gpPassthrough, 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;
+ }
+ }
+}