From 3bcc395253e020df40763d36ba9401b126b17173 Mon Sep 17 00:00:00 2001 From: gdk Date: Sun, 27 Oct 2019 17:51:33 -0300 Subject: [PATCH] Add shader support for the round mode on the F2F instruction, support mipmaps on ASTC compressed textures --- Ryujinx.Graphics.Gpu/Image/Texture.cs | 10 ++++---- .../Glsl/Instructions/InstGenHelper.cs | 1 + .../Instructions/InstEmitConversion.cs | 4 ++++ .../IntermediateRepresentation/Instruction.cs | 1 + .../StructuredIr/InstructionInfo.cs | 1 + .../Translation/EmitterContextInsts.cs | 15 ++++++++---- Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs | 23 ++++++++++++++----- Ryujinx.ShaderTools/Program.cs | 2 +- 8 files changed, 39 insertions(+), 18 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 8da1041be..c34ff1d37 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -250,17 +250,15 @@ namespace Ryujinx.Graphics.Gpu.Image if (!_context.Capabilities.SupportsAstcCompression && _info.FormatInfo.Format.IsAstc()) { - int blockWidth = _info.FormatInfo.BlockWidth; - int blockHeight = _info.FormatInfo.BlockHeight; - data = AstcDecoder.DecodeToRgba8( data, - blockWidth, - blockHeight, + _info.FormatInfo.BlockWidth, + _info.FormatInfo.BlockHeight, 1, _info.Width, _info.Height, - _depth); + _depth, + _info.Levels); } HostTexture.SetData(data); diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs index 6dfbe61ab..24b93afb4 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs @@ -74,6 +74,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions Add(Instruction.Negate, InstType.OpUnary, "-", 0); Add(Instruction.ReciprocalSquareRoot, InstType.CallUnary, "inversesqrt"); Add(Instruction.Return, InstType.OpNullary, "return"); + Add(Instruction.Round, InstType.CallUnary, "roundEven"); Add(Instruction.Sine, InstType.CallUnary, "sin"); Add(Instruction.SquareRoot, InstType.CallUnary, "sqrt"); Add(Instruction.StoreLocal, InstType.Special); diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs index c4de17501..95e9a20a7 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs @@ -29,6 +29,10 @@ namespace Ryujinx.Graphics.Shader.Instructions { switch (op.RoundingMode) { + case RoundingMode.ToNearest: + srcB = context.FPRound(srcB); + break; + case RoundingMode.TowardsNegativeInfinity: srcB = context.FPFloor(srcB); break; diff --git a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs index 74194f35b..88918f3fd 100644 --- a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs +++ b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs @@ -71,6 +71,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation PackHalf2x16, ReciprocalSquareRoot, Return, + Round, ShiftLeft, ShiftRightS32, ShiftRightU32, diff --git a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs index d6ce76db8..675a96785 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs @@ -83,6 +83,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Add(Instruction.Negate, VariableType.Scalar, VariableType.Scalar); Add(Instruction.PackHalf2x16, VariableType.U32, VariableType.F32, VariableType.F32); Add(Instruction.ReciprocalSquareRoot, VariableType.Scalar, VariableType.Scalar); + Add(Instruction.Round, VariableType.F32, VariableType.F32); Add(Instruction.Sine, VariableType.Scalar, VariableType.Scalar); Add(Instruction.SquareRoot, VariableType.Scalar, VariableType.Scalar); Add(Instruction.StoreGlobal, VariableType.None, VariableType.S32, VariableType.S32, VariableType.F32); diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs index f0bede186..7d64e7ca2 100644 --- a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs +++ b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs @@ -171,6 +171,11 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.FP | Instruction.Floor, Local(), a); } + public static Operand FPFusedMultiplyAdd(this EmitterContext context, Operand a, Operand b, Operand c) + { + return context.Add(Instruction.FusedMultiplyAdd, Local(), a, b, c); + } + public static Operand FPLogarithmB2(this EmitterContext context, Operand a) { return context.Add(Instruction.FP | Instruction.LogarithmB2, Local(), a); @@ -191,11 +196,6 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.FP | Instruction.Multiply, Local(), a, b); } - public static Operand FPFusedMultiplyAdd(this EmitterContext context, Operand a, Operand b, Operand c) - { - return context.Add(Instruction.FusedMultiplyAdd, Local(), a, b, c); - } - public static Operand FPNegate(this EmitterContext context, Operand a, bool neg) { if (neg) @@ -221,6 +221,11 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.FP | Instruction.ReciprocalSquareRoot, Local(), a); } + public static Operand FPRound(this EmitterContext context, Operand a) + { + return context.Add(Instruction.FP | Instruction.Round, Local(), a); + } + public static Operand FPSaturate(this EmitterContext context, Operand a, bool sat) { if (sat) diff --git a/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs b/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs index c192a6a9e..0b8172f73 100644 --- a/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs +++ b/Ryujinx.Graphics.Texture/Astc/AstcDecoder.cs @@ -54,7 +54,8 @@ namespace Ryujinx.Graphics.Texture.Astc int blockDepth, int width, int height, - int depth) + int depth, + int levels) { using (MemoryStream inputStream = new MemoryStream(data.ToArray())) { @@ -75,23 +76,28 @@ namespace Ryujinx.Graphics.Texture.Astc { int blockIndex = 0; - for (int j = 0; j < height; j += blockHeight) + int mipOffset = 0; + + for (int l = 0; l < levels; l++) { - for (int i = 0; i < width; i += blockWidth) + for (int j = 0; j < height; j += blockHeight) + for (int i = 0; i < width; i += blockWidth) { int[] decompressedData = new int[144]; DecompressBlock(binReader.ReadBytes(0x10), decompressedData, blockWidth, blockHeight); - int decompressedWidth = Math.Min(blockWidth, width - i); + int decompressedWidth = Math.Min(blockWidth, width - i); int decompressedHeight = Math.Min(blockHeight, height - j); - int baseOffsets = (j * width + i) * 4; + + int baseOffset = mipOffset + (j * width + i) * 4; for (int jj = 0; jj < decompressedHeight; jj++) { - outputStream.Seek(baseOffsets + jj * width * 4, SeekOrigin.Begin); + outputStream.Seek(baseOffset + jj * width * 4, SeekOrigin.Begin); byte[] outputBuffer = new byte[decompressedData.Length * sizeof(int)]; + Buffer.BlockCopy(decompressedData, 0, outputBuffer, 0, outputBuffer.Length); outputStream.Write(outputBuffer, jj * blockWidth * 4, decompressedWidth * 4); @@ -99,6 +105,11 @@ namespace Ryujinx.Graphics.Texture.Astc blockIndex++; } + + mipOffset += width * height * 4; + + width = Math.Max(1, width >> 1); + height = Math.Max(1, height >> 1); } return outputStream.ToArray(); diff --git a/Ryujinx.ShaderTools/Program.cs b/Ryujinx.ShaderTools/Program.cs index cb5805be1..c0afa4f16 100644 --- a/Ryujinx.ShaderTools/Program.cs +++ b/Ryujinx.ShaderTools/Program.cs @@ -10,7 +10,7 @@ namespace Ryujinx.ShaderTools { if (args.Length == 1 || args.Length == 2) { - TranslationFlags flags = TranslationFlags.None; + TranslationFlags flags = TranslationFlags.DebugMode; if (args.Length == 2 && args[0] == "--compute") {