From a15b951721d7c52c30a8e8864e91353ec6fc65f4 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 27 May 2020 20:03:07 -0300 Subject: Fix wrong face culling once and for all (#1277) * Viewport swizzle support on NV and clip origin * Initialize default viewport swizzle state, emulate viewport swizzle on shaders when not supported * Address PR feedback --- .../Translation/EmitterContext.cs | 41 +++++++++++++++++----- .../Translation/TranslationFlags.cs | 5 +-- Ryujinx.Graphics.Shader/Translation/Translator.cs | 2 +- 3 files changed, 37 insertions(+), 11 deletions(-) (limited to 'Ryujinx.Graphics.Shader/Translation') diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs index 8044f074..70476dcd 100644 --- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs +++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs @@ -11,9 +11,7 @@ namespace Ryujinx.Graphics.Shader.Translation public Block CurrBlock { get; set; } public OpCode CurrOp { get; set; } - private ShaderConfig _config; - - public ShaderConfig Config => _config; + public ShaderConfig Config { get; } private List _operations; @@ -21,7 +19,7 @@ namespace Ryujinx.Graphics.Shader.Translation public EmitterContext(ShaderConfig config) { - _config = config; + Config = config; _operations = new List(); @@ -61,13 +59,40 @@ namespace Ryujinx.Graphics.Shader.Translation public void PrepareForReturn() { - if (_config.Stage == ShaderStage.Fragment) + if (Config.Stage == ShaderStage.Vertex && (Config.Flags & TranslationFlags.VertexA) == 0) + { + // Here we attempt to implement viewport swizzle on the vertex shader. + // Perform permutation and negation of the output gl_Position components. + // Note that per-viewport swizzling can't be supported using this approach. + int swizzleX = Config.GpuAccessor.QueryViewportSwizzle(0); + int swizzleY = Config.GpuAccessor.QueryViewportSwizzle(1); + int swizzleZ = Config.GpuAccessor.QueryViewportSwizzle(2); + int swizzleW = Config.GpuAccessor.QueryViewportSwizzle(3); + + bool nonStandardSwizzle = swizzleX != 0 || swizzleY != 2 || swizzleZ != 4 || swizzleW != 6; + + if (!Config.GpuAccessor.QuerySupportsViewportSwizzle() && nonStandardSwizzle) + { + Operand[] temp = new Operand[4]; + + temp[0] = this.Copy(Attribute(AttributeConsts.PositionX)); + temp[1] = this.Copy(Attribute(AttributeConsts.PositionY)); + temp[2] = this.Copy(Attribute(AttributeConsts.PositionZ)); + temp[3] = this.Copy(Attribute(AttributeConsts.PositionW)); + + this.Copy(Attribute(AttributeConsts.PositionX), this.FPNegate(temp[(swizzleX >> 1) & 3], (swizzleX & 1) != 0)); + this.Copy(Attribute(AttributeConsts.PositionY), this.FPNegate(temp[(swizzleY >> 1) & 3], (swizzleY & 1) != 0)); + this.Copy(Attribute(AttributeConsts.PositionZ), this.FPNegate(temp[(swizzleZ >> 1) & 3], (swizzleZ & 1) != 0)); + this.Copy(Attribute(AttributeConsts.PositionW), this.FPNegate(temp[(swizzleW >> 1) & 3], (swizzleW & 1) != 0)); + } + } + else if (Config.Stage == ShaderStage.Fragment) { - if (_config.OmapDepth) + if (Config.OmapDepth) { Operand dest = Attribute(AttributeConsts.FragmentOutputDepth); - Operand src = Register(_config.GetDepthRegister(), RegisterType.Gpr); + Operand src = Register(Config.GetDepthRegister(), RegisterType.Gpr); this.Copy(dest, src); } @@ -76,7 +101,7 @@ namespace Ryujinx.Graphics.Shader.Translation for (int attachment = 0; attachment < 8; attachment++) { - OmapTarget target = _config.OmapTargets[attachment]; + OmapTarget target = Config.OmapTargets[attachment]; for (int component = 0; component < 4; component++) { diff --git a/Ryujinx.Graphics.Shader/Translation/TranslationFlags.cs b/Ryujinx.Graphics.Shader/Translation/TranslationFlags.cs index b8715746..1874dec3 100644 --- a/Ryujinx.Graphics.Shader/Translation/TranslationFlags.cs +++ b/Ryujinx.Graphics.Shader/Translation/TranslationFlags.cs @@ -7,7 +7,8 @@ namespace Ryujinx.Graphics.Shader.Translation { None = 0, - Compute = 1 << 0, - DebugMode = 1 << 1 + VertexA = 1 << 0, + Compute = 1 << 1, + DebugMode = 1 << 2 } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs index fb6935af..1a69c511 100644 --- a/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Shader.Translation public static ShaderProgram Translate(ulong addressA, ulong addressB, IGpuAccessor gpuAccessor, TranslationFlags flags) { - Operation[] opsA = DecodeShader(addressA, gpuAccessor, flags, out _, out int sizeA); + Operation[] opsA = DecodeShader(addressA, gpuAccessor, flags | TranslationFlags.VertexA, out _, out int sizeA); Operation[] opsB = DecodeShader(addressB, gpuAccessor, flags, out ShaderConfig config, out int sizeB); return Translate(Combine(opsA, opsB), config, sizeB, sizeA); -- cgit v1.2.3