aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Shader')
-rw-r--r--src/Ryujinx.Graphics.Shader/AttributeType.cs15
-rw-r--r--src/Ryujinx.Graphics.Shader/IGpuAccessor.cs9
-rw-r--r--src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs26
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/ShaderDefinitions.cs11
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/Translator.cs1
5 files changed, 60 insertions, 2 deletions
diff --git a/src/Ryujinx.Graphics.Shader/AttributeType.cs b/src/Ryujinx.Graphics.Shader/AttributeType.cs
index e6adb4b8..1d950773 100644
--- a/src/Ryujinx.Graphics.Shader/AttributeType.cs
+++ b/src/Ryujinx.Graphics.Shader/AttributeType.cs
@@ -9,6 +9,8 @@ namespace Ryujinx.Graphics.Shader
Float,
Sint,
Uint,
+ Sscaled,
+ Uscaled,
}
static class AttributeTypeExtensions
@@ -23,5 +25,18 @@ namespace Ryujinx.Graphics.Shader
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
};
}
+
+ public static AggregateType ToAggregateType(this AttributeType type, bool supportsScaledFormats)
+ {
+ return type switch
+ {
+ AttributeType.Float => AggregateType.FP32,
+ AttributeType.Sint => AggregateType.S32,
+ AttributeType.Uint => AggregateType.U32,
+ AttributeType.Sscaled => supportsScaledFormats ? AggregateType.FP32 : AggregateType.S32,
+ AttributeType.Uscaled => supportsScaledFormats ? AggregateType.FP32 : AggregateType.U32,
+ _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
+ };
+ }
}
}
diff --git a/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs
index 4c0adc3b..ee31f02d 100644
--- a/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs
+++ b/src/Ryujinx.Graphics.Shader/IGpuAccessor.cs
@@ -267,6 +267,15 @@ namespace Ryujinx.Graphics.Shader
}
/// <summary>
+ /// Queries host support scaled vertex formats, where a integer value is converted to floating-point.
+ /// </summary>
+ /// <returns>True if the host support scaled vertex formats, false otherwise</returns>
+ bool QueryHostSupportsScaledVertexFormats()
+ {
+ return true;
+ }
+
+ /// <summary>
/// Queries host GPU shader ballot support.
/// </summary>
/// <returns>True if the GPU and driver supports shader ballot, false otherwise</returns>
diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs
index 542ec74a..53d774d6 100644
--- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs
+++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitAttribute.cs
@@ -61,7 +61,31 @@ namespace Ryujinx.Graphics.Shader.Instructions
}
else
{
- context.Copy(Register(rd), AttributeMap.GenerateAttributeLoad(context, primVertex, offset, isOutput, op.P));
+ value = AttributeMap.GenerateAttributeLoad(context, primVertex, offset, isOutput, op.P);
+
+ if (!context.TranslatorContext.Definitions.SupportsScaledVertexFormats &&
+ context.TranslatorContext.Stage == ShaderStage.Vertex &&
+ !op.O &&
+ offset >= 0x80 &&
+ offset < 0x280)
+ {
+ // The host does not support scaled vertex formats,
+ // the emulator should use a integer format, and
+ // we compensate here inserting the conversion to float.
+
+ AttributeType type = context.TranslatorContext.Definitions.GetAttributeType((offset - 0x80) >> 4);
+
+ if (type == AttributeType.Sscaled)
+ {
+ value = context.IConvertS32ToFP32(value);
+ }
+ else if (type == AttributeType.Uscaled)
+ {
+ value = context.IConvertU32ToFP32(value);
+ }
+ }
+
+ context.Copy(Register(rd), value);
}
}
else
diff --git a/src/Ryujinx.Graphics.Shader/Translation/ShaderDefinitions.cs b/src/Ryujinx.Graphics.Shader/Translation/ShaderDefinitions.cs
index d278c42e..204f4278 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/ShaderDefinitions.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/ShaderDefinitions.cs
@@ -53,6 +53,8 @@ namespace Ryujinx.Graphics.Shader.Translation
public bool OmapSampleMask { get; }
public bool OmapDepth { get; }
+ public bool SupportsScaledVertexFormats { get; }
+
public bool TransformFeedbackEnabled { get; }
private readonly TransformFeedbackOutput[] _transformFeedbackOutputs;
@@ -139,6 +141,7 @@ namespace Ryujinx.Graphics.Shader.Translation
int omapTargets,
bool omapSampleMask,
bool omapDepth,
+ bool supportsScaledVertexFormats,
bool transformFeedbackEnabled,
ulong transformFeedbackVecMap,
TransformFeedbackOutput[] transformFeedbackOutputs)
@@ -154,6 +157,7 @@ namespace Ryujinx.Graphics.Shader.Translation
OmapSampleMask = omapSampleMask;
OmapDepth = omapDepth;
LastInVertexPipeline = stage < ShaderStage.Fragment;
+ SupportsScaledVertexFormats = supportsScaledVertexFormats;
TransformFeedbackEnabled = transformFeedbackEnabled;
_transformFeedbackOutputs = transformFeedbackOutputs;
_transformFeedbackDefinitions = new();
@@ -302,7 +306,7 @@ namespace Ryujinx.Graphics.Shader.Translation
if (Stage == ShaderStage.Vertex && !isOutput)
{
- type |= _graphicsState.AttributeTypes[location].ToAggregateType();
+ type |= _graphicsState.AttributeTypes[location].ToAggregateType(SupportsScaledVertexFormats);
}
else
{
@@ -311,5 +315,10 @@ namespace Ryujinx.Graphics.Shader.Translation
return type;
}
+
+ public AttributeType GetAttributeType(int location)
+ {
+ return _graphicsState.AttributeTypes[location];
+ }
}
}
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs
index b609ac07..93a70ace 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/Translator.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/Translator.cs
@@ -116,6 +116,7 @@ namespace Ryujinx.Graphics.Shader.Translation
header.OmapTargets,
header.OmapSampleMask,
header.OmapDepth,
+ gpuAccessor.QueryHostSupportsScaledVertexFormats(),
transformFeedbackEnabled,
transformFeedbackVecMap,
transformFeedbackOutputs);