diff --git a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
index ae128ed43..e6d46884a 100644
--- a/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
+++ b/Ryujinx.Graphics.Gpu/Shader/ShaderCache.cs
@@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
///
/// Version of the codegen (to be changed when codegen or guest format change).
///
- private const ulong ShaderCodeGenVersion = 3132;
+ private const ulong ShaderCodeGenVersion = 3054;
// Progress reporting helpers
private volatile int _shaderCount;
diff --git a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
index 8820527f1..6fa4055aa 100644
--- a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
@@ -308,7 +308,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
int attr = offset + elemIndex * 4;
if (attr >= AttributeConsts.UserAttributeBase && attr < AttributeConsts.UserAttributeEnd)
{
- int index = (attr - AttributeConsts.UserAttributeBase) / 16;
+ int userAttr = attr - AttributeConsts.UserAttributeBase;
+ int index = userAttr / 16;
if (isStore)
{
@@ -316,7 +317,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
else
{
- config.SetInputUserAttribute(index, perPatch);
+ config.SetInputUserAttribute(index, (userAttr >> 2) & 3, perPatch);
}
}
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index 3b10ab211..8be7ceaea 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -54,6 +54,11 @@ namespace Ryujinx.Graphics.Shader.Translation
private int _nextUsedInputAttributes;
private int _thisUsedInputAttributes;
+ public UInt128 NextInputAttributesComponents { get; private set; }
+ public UInt128 ThisInputAttributesComponents { get; private set; }
+ public UInt128 NextInputAttributesPerPatchComponents { get; private set; }
+ public UInt128 ThisInputAttributesPerPatchComponents { get; private set; }
+
private int _usedConstantBuffers;
private int _usedStorageBuffers;
private int _usedStorageBuffersWrite;
@@ -227,11 +232,12 @@ namespace Ryujinx.Graphics.Shader.Translation
UsedOutputAttributes |= 1 << index;
}
- public void SetInputUserAttribute(int index, bool perPatch)
+ public void SetInputUserAttribute(int index, int component, bool perPatch)
{
if (perPatch)
{
UsedInputAttributesPerPatch |= 1 << index;
+ ThisInputAttributesPerPatchComponents |= UInt128.Pow2(index * 4 + component);
}
else
{
@@ -239,6 +245,7 @@ namespace Ryujinx.Graphics.Shader.Translation
UsedInputAttributes |= mask;
_thisUsedInputAttributes |= mask;
+ ThisInputAttributesComponents |= UInt128.Pow2(index * 4 + component);
}
}
@@ -256,6 +263,8 @@ namespace Ryujinx.Graphics.Shader.Translation
public void MergeFromtNextStage(ShaderConfig config)
{
+ NextInputAttributesComponents = config.ThisInputAttributesComponents;
+ NextInputAttributesPerPatchComponents = config.ThisInputAttributesPerPatchComponents;
NextUsesFixedFuncAttributes = config.UsedFeatures.HasFlag(FeatureFlags.FixedFuncAttr);
MergeOutputUserAttributes(config.UsedInputAttributes, config.UsedInputAttributesPerPatch);
}
diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs
index 603b20d64..e594c818a 100644
--- a/Ryujinx.Graphics.Shader/Translation/Translator.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs
@@ -214,24 +214,24 @@ namespace Ryujinx.Graphics.Shader.Translation
InitializeOutput(context, AttributeConsts.PositionX, perPatch: false);
}
- int usedAttributes = context.Config.UsedOutputAttributes;
- while (usedAttributes != 0)
+ UInt128 usedAttributes = context.Config.NextInputAttributesComponents;
+ while (usedAttributes != UInt128.Zero)
{
- int index = BitOperations.TrailingZeroCount(usedAttributes);
+ int index = usedAttributes.TrailingZeroCount();
- InitializeOutput(context, AttributeConsts.UserAttributeBase + index * 16, perPatch: false);
+ InitializeOutputComponent(context, AttributeConsts.UserAttributeBase + index * 4, perPatch: false);
- usedAttributes &= ~(1 << index);
+ usedAttributes &= ~UInt128.Pow2(index);
}
- int usedAttributesPerPatch = context.Config.UsedOutputAttributesPerPatch;
- while (usedAttributesPerPatch != 0)
+ UInt128 usedAttributesPerPatch = context.Config.NextInputAttributesPerPatchComponents;
+ while (usedAttributesPerPatch != UInt128.Zero)
{
- int index = BitOperations.TrailingZeroCount(usedAttributesPerPatch);
+ int index = usedAttributesPerPatch.TrailingZeroCount();
- InitializeOutput(context, AttributeConsts.UserAttributeBase + index * 16, perPatch: true);
+ InitializeOutputComponent(context, AttributeConsts.UserAttributeBase + index * 4, perPatch: true);
- usedAttributesPerPatch &= ~(1 << index);
+ usedAttributesPerPatch &= ~UInt128.Pow2(index);
}
if (config.NextUsesFixedFuncAttributes)
@@ -260,6 +260,12 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
+ private static void InitializeOutputComponent(EmitterContext context, int attrOffset, bool perPatch)
+ {
+ int c = (attrOffset >> 2) & 3;
+ context.Copy(perPatch ? AttributePerPatch(attrOffset) : Attribute(attrOffset), ConstF(c == 3 ? 1f : 0f));
+ }
+
private static void EmitOps(EmitterContext context, Block block)
{
for (int opIndex = 0; opIndex < block.OpCodes.Count; opIndex++)
diff --git a/Ryujinx.Graphics.Shader/Translation/UInt128.cs b/Ryujinx.Graphics.Shader/Translation/UInt128.cs
new file mode 100644
index 000000000..590f7690f
--- /dev/null
+++ b/Ryujinx.Graphics.Shader/Translation/UInt128.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Numerics;
+
+namespace Ryujinx.Graphics.Shader.Translation
+{
+ struct UInt128 : IEquatable
+ {
+ public static UInt128 Zero => new UInt128() { _v0 = 0, _v1 = 0 };
+
+ private ulong _v0;
+ private ulong _v1;
+
+ public int TrailingZeroCount()
+ {
+ int count = BitOperations.TrailingZeroCount(_v0);
+ if (count == 64)
+ {
+ count += BitOperations.TrailingZeroCount(_v1);
+ }
+
+ return count;
+ }
+
+ public static UInt128 Pow2(int x)
+ {
+ if (x >= 64)
+ {
+ return new UInt128() { _v0 = 0, _v1 = 1UL << (x - 64 ) };
+ }
+
+ return new UInt128() { _v0 = 1UL << x, _v1 = 0 };
+ }
+
+ public static UInt128 operator ~(UInt128 x)
+ {
+ return new UInt128() { _v0 = ~x._v0, _v1 = ~x._v1 };
+ }
+
+ public static UInt128 operator &(UInt128 x, UInt128 y)
+ {
+ return new UInt128() { _v0 = x._v0 & y._v0, _v1 = x._v1 & y._v1 };
+ }
+
+ public static UInt128 operator |(UInt128 x, UInt128 y)
+ {
+ return new UInt128() { _v0 = x._v0 | y._v0, _v1 = x._v1 | y._v1 };
+ }
+
+ public static bool operator ==(UInt128 x, UInt128 y)
+ {
+ return x.Equals(y);
+ }
+
+ public static bool operator !=(UInt128 x, UInt128 y)
+ {
+ return !x.Equals(y);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is UInt128 other && Equals(other);
+ }
+
+ public bool Equals(UInt128 other)
+ {
+ return _v0 == other._v0 && _v1 == other._v1;
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine(_v0, _v1);
+ }
+ }
+}
\ No newline at end of file