From effd546331371928bc38bc8a48b0c26c7c59f3e9 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 16 Aug 2023 08:30:33 -0300 Subject: Implement scaled vertex format emulation (#5564) * Implement scaled vertex format emulation * Auto-format (whitespace) * Delete ToVec4Type --- src/Ryujinx.Graphics.Shader/AttributeType.cs | 15 +++++++++++++ src/Ryujinx.Graphics.Shader/IGpuAccessor.cs | 9 ++++++++ .../Instructions/InstEmitAttribute.cs | 26 +++++++++++++++++++++- .../Translation/ShaderDefinitions.cs | 11 ++++++++- .../Translation/Translator.cs | 1 + 5 files changed, 60 insertions(+), 2 deletions(-) (limited to 'src/Ryujinx.Graphics.Shader') 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 @@ -266,6 +266,15 @@ namespace Ryujinx.Graphics.Shader return true; } + /// + /// Queries host support scaled vertex formats, where a integer value is converted to floating-point. + /// + /// True if the host support scaled vertex formats, false otherwise + bool QueryHostSupportsScaledVertexFormats() + { + return true; + } + /// /// Queries host GPU shader ballot support. /// 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); -- cgit v1.2.3