From b9a8380ac58fa33d3b04c20e3370c2108f0699cd Mon Sep 17 00:00:00 2001 From: Thog Date: Tue, 6 Nov 2018 23:21:37 +0100 Subject: [PATCH] Initial non 2D textures support - Shaders still need to be changed - Some types aren't yet implemented --- Ryujinx.Graphics/Gal/GalImage.cs | 6 + Ryujinx.Graphics/Gal/IGalTexture.cs | 2 +- .../Gal/OpenGL/OGLRenderTarget.cs | 6 +- Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs | 160 +++++++++++++---- Ryujinx.Graphics/Gal/Shader/GlslDecl.cs | 18 +- Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 63 ++++++- .../Gal/Shader/ShaderDecodeMem.cs | 162 ++++++++++++++++-- .../Gal/Shader/ShaderIrMetaTex.cs | 10 +- Ryujinx.Graphics/Gal/ShaderDeclInfo.cs | 18 +- Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs | 12 +- Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs | 7 +- .../Graphics3d/Texture/ImageUtils.cs | 26 +++ .../Graphics3d/Texture/TextureFactory.cs | 11 ++ Ryujinx.Graphics/Texture/TextureType.cs | 15 ++ Ryujinx.Graphics/VDec/VideoDecoder.cs | 5 +- Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs | 7 +- 16 files changed, 460 insertions(+), 68 deletions(-) create mode 100644 Ryujinx.Graphics/Texture/TextureType.cs diff --git a/Ryujinx.Graphics/Gal/GalImage.cs b/Ryujinx.Graphics/Gal/GalImage.cs index 92f43cc9d4..f35cccaf77 100644 --- a/Ryujinx.Graphics/Gal/GalImage.cs +++ b/Ryujinx.Graphics/Gal/GalImage.cs @@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.Gal { public int Width; public int Height; + public int Depth; public int TileWidth; public int GobBlockHeight; public int Pitch; @@ -16,14 +17,17 @@ namespace Ryujinx.Graphics.Gal public GalTextureSource YSource; public GalTextureSource ZSource; public GalTextureSource WSource; + public TextureType TextureType; public GalImage( int Width, int Height, + int Depth, int TileWidth, int GobBlockHeight, GalMemoryLayout Layout, GalImageFormat Format, + TextureType TextureType, GalTextureSource XSource = GalTextureSource.Red, GalTextureSource YSource = GalTextureSource.Green, GalTextureSource ZSource = GalTextureSource.Blue, @@ -31,6 +35,7 @@ namespace Ryujinx.Graphics.Gal { this.Width = Width; this.Height = Height; + this.Depth = Depth; this.TileWidth = TileWidth; this.GobBlockHeight = GobBlockHeight; this.Layout = Layout; @@ -39,6 +44,7 @@ namespace Ryujinx.Graphics.Gal this.YSource = YSource; this.ZSource = ZSource; this.WSource = WSource; + this.TextureType = TextureType; Pitch = ImageUtils.GetPitch(Format, Width); } diff --git a/Ryujinx.Graphics/Gal/IGalTexture.cs b/Ryujinx.Graphics/Gal/IGalTexture.cs index aeecdf1ac5..de4ba9cba7 100644 --- a/Ryujinx.Graphics/Gal/IGalTexture.cs +++ b/Ryujinx.Graphics/Gal/IGalTexture.cs @@ -13,6 +13,6 @@ namespace Ryujinx.Graphics.Gal void Bind(long Key, int Index, GalImage Image); - void SetSampler(GalTextureSampler Sampler); + void SetSampler(GalImage Image, GalTextureSampler Sampler); } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs index 0d7bb3cd0a..392eb29786 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs @@ -477,9 +477,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL (_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format); - GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle); + TextureTarget Target = ImageUtils.GetTextureTarget(NewImage.TextureType); - GL.GetTexImage(TextureTarget.Texture2D, 0, Format, Type, IntPtr.Zero); + GL.BindTexture(Target, CachedImage.Handle); + + GL.GetTexImage(Target, 0, Format, Type, IntPtr.Zero); GL.BindBuffer(BufferTarget.PixelPackBuffer, 0); GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs index ef984b1ed3..802d02e690 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs @@ -1,4 +1,5 @@ using OpenTK.Graphics.OpenGL; +using Ryujinx.Common.Logging; using Ryujinx.Graphics.Texture; using System; @@ -38,7 +39,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL { int Handle = GL.GenTexture(); - GL.BindTexture(TextureTarget.Texture2D, Handle); + TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureType); + + GL.BindTexture(Target, Handle); const int Level = 0; //TODO: Support mipmap textures. const int Border = 0; @@ -54,23 +57,60 @@ namespace Ryujinx.Graphics.Gal.OpenGL PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format); - GL.TexImage2D( - TextureTarget.Texture2D, - Level, - InternalFmt, - Image.Width, - Image.Height, - Border, - Format, - Type, - IntPtr.Zero); + switch (Target) + { + case TextureTarget.Texture2D: + GL.TexImage2D( + Target, + Level, + InternalFmt, + Image.Width, + Image.Height, + Border, + Format, + Type, + IntPtr.Zero); + break; + case TextureTarget.Texture2DArray: + case TextureTarget.Texture3D: + GL.TexImage3D( + Target, + Level, + InternalFmt, + Image.Width, + Image.Height, + Image.Depth, + Border, + Format, + Type, + IntPtr.Zero); + break; + default: + Logger.PrintWarning(LogClass.Gpu, $"Unsupported texture target type: {Target}"); + //throw new InvalidOperationException(); + GL.TexImage2D( + TextureTarget.Texture2D, + Level, + InternalFmt, + Image.Width, + Image.Height, + Border, + Format, + Type, + IntPtr.Zero); + break; + } + + } public void Create(long Key, byte[] Data, GalImage Image) { int Handle = GL.GenTexture(); - GL.BindTexture(TextureTarget.Texture2D, Handle); + TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureType); + + GL.BindTexture(Target, Handle); const int Level = 0; //TODO: Support mipmap textures. const int Border = 0; @@ -81,15 +121,72 @@ namespace Ryujinx.Graphics.Gal.OpenGL { InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format); - GL.CompressedTexImage2D( - TextureTarget.Texture2D, - Level, - InternalFmt, - Image.Width, - Image.Height, - Border, - Data.Length, - Data); + switch (Target) + { + case TextureTarget.Texture2D: + GL.CompressedTexImage2D( + Target, + Level, + InternalFmt, + Image.Width, + Image.Height, + Border, + Data.Length, + Data); + break; + case TextureTarget.Texture2DArray: + case TextureTarget.Texture3D: + GL.CompressedTexImage3D( + Target, + Level, + InternalFmt, + Image.Width, + Image.Height, + Image.Depth, + Border, + Data.Length, + Data); + break; + case TextureTarget.TextureCubeMap: + for (int i = 0; i < 6; i++) + { + GL.CompressedTexImage2D( + TextureTarget.TextureCubeMapPositiveX + i, + Level, + InternalFmt, + Image.Width, + Image.Height, + Border, + Data.Length, // FIXME: NOT SURE OF THIS + Data); + } + break; + case TextureTarget.TextureCubeMapArray: + GL.CompressedTexImage3D( + Target, + Level, + InternalFmt, + Image.Width, + Image.Height, + Image.Depth * 6, + Border, + Data.Length, + Data); + break; + default: + Logger.PrintWarning(LogClass.Gpu, $"Unsupported texture target type: {Target} ({Image.Depth})"); + throw new InvalidOperationException(); + GL.CompressedTexImage2D( + TextureTarget.Texture2D, + Level, + InternalFmt, + Image.Width, + Image.Height, + Border, + Data.Length, + Data); + break; + } } else { @@ -99,6 +196,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format); int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format); + // TODO: support 3D textures Data = ASTCDecoder.DecodeToRGBA8888( Data, TextureBlockWidth, @@ -165,7 +263,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL { GL.ActiveTexture(TextureUnit.Texture0 + Index); - GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle); + TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureType); + + GL.BindTexture(Target, CachedImage.Handle); int[] SwizzleRgba = new int[] { @@ -175,11 +275,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource) }; - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, SwizzleRgba); + GL.TexParameter(Target, TextureParameterName.TextureSwizzleRgba, SwizzleRgba); } } - public void SetSampler(GalTextureSampler Sampler) + public void SetSampler(GalImage Image, GalTextureSampler Sampler) { int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU); int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV); @@ -187,11 +287,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter); int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, WrapS); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, WrapT); + TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureType); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter); + GL.TexParameter(Target, TextureParameterName.TextureWrapS, WrapS); + GL.TexParameter(Target, TextureParameterName.TextureWrapT, WrapT); + + GL.TexParameter(Target, TextureParameterName.TextureMinFilter, MinFilter); + GL.TexParameter(Target, TextureParameterName.TextureMagFilter, MagFilter); float[] Color = new float[] { @@ -201,7 +303,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL Sampler.BorderColor.Alpha }; - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color); + GL.TexParameter(Target, TextureParameterName.TextureBorderColor, Color); } } } diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index 43923da742..bd422657fd 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -1,3 +1,5 @@ +using Ryujinx.Graphics.Gal.OpenGL; +using Ryujinx.Graphics.Texture; using System; using System.Collections.Generic; @@ -232,7 +234,19 @@ namespace Ryujinx.Graphics.Gal.Shader string Name = StagePrefix + TextureName + Index; - m_Textures.TryAdd(Handle, new ShaderDeclInfo(Name, Handle)); + TextureType TextureType; + + // TODO: non 2d texture type for TEXQ? + if (Op.Inst == ShaderIrInst.Texq) + { + TextureType = TextureType.TwoD; + } + else + { + TextureType = ((ShaderIrMetaTex)Op.MetaData).TextureType; + } + + m_Textures.TryAdd(Handle, new ShaderDeclInfo(Name, Handle, false, 0, 1, TextureType)); } else if (Op.Inst == ShaderIrInst.Texb) { @@ -259,7 +273,7 @@ namespace Ryujinx.Graphics.Gal.Shader { string Name = StagePrefix + TextureName + "_cb" + Cbuf.Index + "_" + Cbuf.Pos; - m_CbTextures.Add(Op, new ShaderDeclInfo(Name, Cbuf.Pos, true, Cbuf.Index)); + m_CbTextures.Add(Op, new ShaderDeclInfo(Name, Cbuf.Pos, true, Cbuf.Index, 1, ((ShaderIrMetaTex)Op.MetaData).TextureType)); } else { diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index 854c827ee0..e9a6279a2e 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -1,3 +1,5 @@ +using OpenTK.Graphics.OpenGL; +using Ryujinx.Graphics.Texture; using System; using System.Collections.Generic; using System.Globalization; @@ -219,14 +221,52 @@ namespace Ryujinx.Graphics.Gal.Shader } } + private string GetSamplerType(TextureTarget TextureTarget) + { + switch (TextureTarget) + { + case TextureTarget.Texture1D: + return "sampler1D"; + case TextureTarget.Texture2D: + return "sampler2D"; + case TextureTarget.Texture3D: + return "sampler3D"; + case TextureTarget.TextureCubeMap: + return "samplerCube"; + case TextureTarget.TextureRectangle: + return "sampler2DRect"; + case TextureTarget.Texture1DArray: + return "sampler1DArray"; + case TextureTarget.Texture2DArray: + return "sampler2DArray"; + case TextureTarget.TextureCubeMapArray: + return "samplerCubeArray"; + case TextureTarget.TextureBuffer: + return "samplerBuffer"; + case TextureTarget.Texture2DMultisample: + return "sampler2DMS"; + case TextureTarget.Texture2DMultisampleArray: + return "sampler2DMSArray"; + default: + throw new NotSupportedException(); + } + } + private void PrintDeclTextures() { foreach (ShaderDeclInfo DeclInfo in IterateCbTextures()) { - SB.AppendLine("uniform sampler2D " + DeclInfo.Name + ";"); + TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType); + + SB.AppendLine("uniform " + GetSamplerType(Target) + " " + DeclInfo.Name + ";"); } - PrintDecls(Decl.Textures, "uniform sampler2D"); + foreach (ShaderDeclInfo DeclInfo in Decl.Textures.Values.OrderBy(DeclKeySelector)) + { + TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType); + + SB.AppendLine("uniform " + GetSamplerType(Target) + " " + DeclInfo.Name + ";"); + } } private IEnumerable IterateCbTextures() @@ -1246,8 +1286,23 @@ namespace Ryujinx.Graphics.Gal.Shader private string GetTexSamplerCoords(ShaderIrOp Op) { - return "vec2(" + GetOperExpr(Op, Op.OperandA) + ", " + - GetOperExpr(Op, Op.OperandB) + ")"; + ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData; + + switch (Meta.TextureType) + { + case TextureType.OneD: + return GetOperExpr(Op, Meta.Coordinates[0]); + case TextureType.ThreeD: + case TextureType.TwoDArray: + case TextureType.CubeMap: + return "vec3(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + GetOperExpr(Op, Meta.Coordinates[1]) + ", " + GetOperExpr(Op, Meta.Coordinates[2]) + ")"; + case TextureType.CubeArray: + return "vec4(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + GetOperExpr(Op, Meta.Coordinates[1]) + ", " + GetOperExpr(Op, Meta.Coordinates[2]) + ", " + GetOperExpr(Op, Meta.Coordinates[3]) + ")"; + case TextureType.TwoD: + default: + return "vec2(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + GetOperExpr(Op, Meta.Coordinates[1]) + ")"; + } + } private string GetITexSamplerCoords(ShaderIrOp Op) diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs index adcc47b955..7013aac98b 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs @@ -1,3 +1,4 @@ +using Ryujinx.Graphics.Texture; using System; using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper; @@ -29,6 +30,68 @@ namespace Ryujinx.Graphics.Gal.Shader { RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ } }; + private static TextureType TexToTextureType(int TexType) + { + switch (TexType) + { + case 2: + return TextureType.TwoD; + case 4: + return TextureType.ThreeD; + case 6: + return TextureType.CubeMap; + default: + throw new InvalidOperationException(); + } + } + + private static int GetCoordsCountTextureType(TextureType TextureType) + { + switch (TextureType) + { + case TextureType.OneD: + return 1; + case TextureType.OneDArray: + case TextureType.TwoD: + case TextureType.TwoDNoMipMap: + return 2; + case TextureType.ThreeD: + case TextureType.TwoDArray: + case TextureType.CubeMap: + return 3; + default: + throw new NotImplementedException($"TEX of TextureTpe.{TextureType} not implemented"); + } + } + + private static TextureType TexsToTextureType(int TexType) + { + switch (TexType) + { + case 0: + return TextureType.OneD; + case 2: + case 4: + case 6: + case 8: + case 0xa: + case 0xc: + return TextureType.TwoD; + case 0xe: + case 0x10: + case 0x12: + return TextureType.TwoDArray; + case 0x14: + case 0x16: + return TextureType.ThreeD; + case 0x18: + case 0x1a: + return TextureType.CubeArray; + default: + throw new InvalidOperationException(); + } + } + public static void Ld_A(ShaderIrBlock Block, long OpCode, int Position) { ShaderIrNode[] Opers = OpCode.Abuf20(); @@ -142,8 +205,12 @@ namespace Ryujinx.Graphics.Gal.Shader private static void EmitTex(ShaderIrBlock Block, long OpCode, bool GprHandle) { - //TODO: Support other formats. - ShaderIrOperGpr[] Coords = new ShaderIrOperGpr[2]; + // TODO: Support array textures + TextureType TextureType = TexToTextureType(OpCode.Read(28, 6)); + Block.AddNode(new ShaderIrCmnt($"TextureType: {TextureType}")); + + // FIXME: check if this is right + ShaderIrOperGpr[] Coords = new ShaderIrOperGpr[GetCoordsCountTextureType(TextureType)]; for (int Index = 0; Index < Coords.Length; Index++) { @@ -187,7 +254,7 @@ namespace Ryujinx.Graphics.Gal.Shader continue; } - ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch); + ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch, TextureType, Coords); ShaderIrOp Op = new ShaderIrOp(Inst, Coords[0], Coords[1], OperC, Meta); @@ -207,7 +274,73 @@ namespace Ryujinx.Graphics.Gal.Shader private static void EmitTexs(ShaderIrBlock Block, long OpCode, ShaderIrInst Inst) { + TextureType TextureType = TexsToTextureType(OpCode.Read(52, 0x1e)); + Block.AddNode(new ShaderIrCmnt($"TextureType: {TextureType}")); + + if (Inst == ShaderIrInst.Txlf && TextureType == TextureType.CubeArray) + { + throw new InvalidOperationException("TXLF instructions cannot use CUBE modifier!"); + } + //TODO: Support other formats. + ShaderIrOperGpr OperA = OpCode.Gpr8(); + ShaderIrOperGpr OperB = OpCode.Gpr20(); + + ShaderIrOperGpr[] GetCoordinates() + { + ShaderIrOperGpr X; + ShaderIrOperGpr Y; + ShaderIrOperGpr Z; + ShaderIrOperGpr Index; + + switch (TextureType) + { + case TextureType.OneD: + X = OperA; + + return CoordsRegistersToTempRegisters(Block, X); + case TextureType.TwoDArray: + Index = OperA; + + X = OpCode.Gpr8(); + X.Index++; + + Y = OperB; + + return CoordsRegistersToTempRegisters(Block, X, Y, Index); + case TextureType.ThreeD: + case TextureType.CubeMap: + X = OperA; + + Y = OpCode.Gpr8(); + Y.Index += 1; + + Z = OperB; + + return CoordsRegistersToTempRegisters(Block, X, Y, Z); + case TextureType.CubeArray: + Index = OperA; + + X = OpCode.Gpr8(); + X.Index += 1; + + Y = OpCode.Gpr8(); + Y.Index += 2; + + Z = OperB; + + return CoordsRegistersToTempRegisters(Block, X, Y, Z, Index); + case TextureType.TwoD: + X = OperA; + Y = OperB; + + return new ShaderIrOperGpr[] { X, Y }; + default: + throw new NotImplementedException($"TEXS of TextureType.{TextureType} not supported!"); + } + } + + int LutIndex; LutIndex = !OpCode.Gpr0().IsConst ? 1 : 0; @@ -277,12 +410,6 @@ namespace Ryujinx.Graphics.Gal.Shader ShaderIrNode OperC = OpCode.Imm13_36(); - ShaderIrOperGpr Coord0 = ShaderIrOperGpr.MakeTemporary(0); - ShaderIrOperGpr Coord1 = ShaderIrOperGpr.MakeTemporary(1); - - Block.AddNode(new ShaderIrAsg(Coord0, OpCode.Gpr8())); - Block.AddNode(new ShaderIrAsg(Coord1, OpCode.Gpr20())); - for (int Ch = 0; Ch < 4; Ch++) { if (!IsChannelUsed(ChMask, Ch)) @@ -290,9 +417,9 @@ namespace Ryujinx.Graphics.Gal.Shader continue; } - ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch); + ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch, TextureType, GetCoordinates()); - ShaderIrOp Op = new ShaderIrOp(Inst, Coord0, Coord1, OperC, Meta); + ShaderIrOp Op = new ShaderIrOp(Inst, OperA, OperB, OperC, Meta); ShaderIrOperGpr Dst = GetDst(); @@ -307,5 +434,18 @@ namespace Ryujinx.Graphics.Gal.Shader { return (ChMask & (1 << Ch)) != 0; } + + private static ShaderIrOperGpr[] CoordsRegistersToTempRegisters(ShaderIrBlock Block, params ShaderIrOperGpr[] Registers) + { + ShaderIrOperGpr[] Res = new ShaderIrOperGpr[Registers.Length]; + + for (int Index = 0; Index < Res.Length; Index++) + { + Res[Index] = ShaderIrOperGpr.MakeTemporary(Index); + Block.AddNode(new ShaderIrAsg(Res[Index], Registers[Index])); + } + + return Res; + } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs index 82f3bb774a..27f67961b4 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs @@ -1,12 +1,18 @@ +using Ryujinx.Graphics.Texture; + namespace Ryujinx.Graphics.Gal.Shader { class ShaderIrMetaTex : ShaderIrMeta { public int Elem { get; private set; } + public TextureType TextureType { get; private set; } + public ShaderIrNode[] Coordinates { get; private set; } - public ShaderIrMetaTex(int Elem) + public ShaderIrMetaTex(int Elem, TextureType TextureType, params ShaderIrNode[] Coordinates) { - this.Elem = Elem; + this.Elem = Elem; + this.TextureType = TextureType; + this.Coordinates = Coordinates; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/ShaderDeclInfo.cs b/Ryujinx.Graphics/Gal/ShaderDeclInfo.cs index ef47ca2e1b..486716d076 100644 --- a/Ryujinx.Graphics/Gal/ShaderDeclInfo.cs +++ b/Ryujinx.Graphics/Gal/ShaderDeclInfo.cs @@ -1,3 +1,5 @@ +using Ryujinx.Graphics.Texture; + namespace Ryujinx.Graphics.Gal { public class ShaderDeclInfo @@ -9,18 +11,22 @@ namespace Ryujinx.Graphics.Gal public int Cbuf { get; private set; } public int Size { get; private set; } + public TextureType TextureType { get; private set; } + public ShaderDeclInfo( string Name, int Index, bool IsCb = false, int Cbuf = 0, - int Size = 1) + int Size = 1, + TextureType TextureType = TextureType.TwoD) { - this.Name = Name; - this.Index = Index; - this.IsCb = IsCb; - this.Cbuf = Cbuf; - this.Size = Size; + this.Name = Name; + this.Index = Index; + this.IsCb = IsCb; + this.Cbuf = Cbuf; + this.Size = Size; + this.TextureType = TextureType; } internal void Enlarge(int NewSize) diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs index 55e3ebd4c4..c6332df57a 100644 --- a/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs +++ b/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs @@ -82,19 +82,23 @@ namespace Ryujinx.Graphics.Graphics3d long SrcKey = Vmm.GetPhysicalAddress(SrcAddress); long DstKey = Vmm.GetPhysicalAddress(DstAddress); + // TODO: all texture types + GalImage SrcTexture = new GalImage( SrcWidth, - SrcHeight, 1, + SrcHeight, 1, 1, SrcBlockHeight, SrcLayout, - SrcImgFormat); + SrcImgFormat, + TextureType.TwoD); GalImage DstTexture = new GalImage( DstWidth, - DstHeight, 1, + DstHeight, 1, 1, DstBlockHeight, DstLayout, - DstImgFormat); + DstImgFormat, + TextureType.TwoD); SrcTexture.Pitch = SrcPitch; DstTexture.Pitch = DstPitch; diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs index 1ca3ca1ce1..7d335ea740 100644 --- a/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs @@ -208,7 +208,7 @@ namespace Ryujinx.Graphics.Graphics3d GalImageFormat Format = ImageUtils.ConvertSurface((GalSurfaceFormat)SurfFormat); - GalImage Image = new GalImage(Width, Height, 1, GobBlockHeight, Layout, Format); + GalImage Image = new GalImage(Width, Height, 1, 1, GobBlockHeight, Layout, Format, TextureType.TwoD); Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image); @@ -262,7 +262,8 @@ namespace Ryujinx.Graphics.Graphics3d GalImageFormat Format = ImageUtils.ConvertZeta((GalZetaFormat)ZetaFormat); - GalImage Image = new GalImage(Width, Height, 1, GobBlockHeight, Layout, Format); + // TODO: all texture types + GalImage Image = new GalImage(Width, Height, 1, 1, GobBlockHeight, Layout, Format, TextureType.TwoD); Gpu.ResourceManager.SendZetaBuffer(Vmm, Key, Image); } @@ -598,7 +599,7 @@ namespace Ryujinx.Graphics.Graphics3d } Gpu.Renderer.Texture.Bind(Key, Index, Image); - Gpu.Renderer.Texture.SetSampler(Sampler); + Gpu.Renderer.Texture.SetSampler(Image, Sampler); } } diff --git a/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs b/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs index f958e1de81..46ee1a725f 100644 --- a/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs +++ b/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs @@ -3,6 +3,7 @@ using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Memory; using System; using System.Collections.Generic; +using OpenTK.Graphics.OpenGL; namespace Ryujinx.Graphics.Texture { @@ -336,6 +337,7 @@ namespace Ryujinx.Graphics.Texture int Width = DivRoundUp(Image.Width, Desc.BlockWidth); int Height = DivRoundUp(Image.Height, Desc.BlockHeight); + // TODO: multi format return Desc.BytesPerPixel * Width * Height; } @@ -443,5 +445,29 @@ namespace Ryujinx.Graphics.Texture default: throw new NotImplementedException(((int)Type).ToString()); } } + + public static TextureTarget GetTextureTarget(TextureType TextureType) + { + switch (TextureType) + { + case TextureType.OneD: + return TextureTarget.Texture1D; + case TextureType.TwoD: + case TextureType.TwoDNoMipMap: + return TextureTarget.Texture2D; + case TextureType.ThreeD: + return TextureTarget.Texture3D; + case TextureType.OneDArray: + return TextureTarget.Texture1DArray; + case TextureType.TwoDArray: + return TextureTarget.Texture2DArray; + case TextureType.CubeMap: + return TextureTarget.TextureCubeMap; + case TextureType.CubeArray: + return TextureTarget.TextureCubeMapArray; + default: + throw new NotSupportedException($"Texture type {TextureType} currently not supported!"); + } + } } } diff --git a/Ryujinx.Graphics/Graphics3d/Texture/TextureFactory.cs b/Ryujinx.Graphics/Graphics3d/Texture/TextureFactory.cs index 1f2d625ec4..f636b6e2d9 100644 --- a/Ryujinx.Graphics/Graphics3d/Texture/TextureFactory.cs +++ b/Ryujinx.Graphics/Graphics3d/Texture/TextureFactory.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Memory; using System; @@ -12,6 +13,8 @@ namespace Ryujinx.Graphics.Texture GalImageFormat Format = GetImageFormat(Tic); + TextureType TextureType = (TextureType)((Tic[4] >> 23) & 0xF); + GalTextureSource XSource = (GalTextureSource)((Tic[0] >> 19) & 7); GalTextureSource YSource = (GalTextureSource)((Tic[0] >> 22) & 7); GalTextureSource ZSource = (GalTextureSource)((Tic[0] >> 25) & 7); @@ -39,14 +42,22 @@ namespace Ryujinx.Graphics.Texture int Width = (Tic[4] & 0xffff) + 1; int Height = (Tic[5] & 0xffff) + 1; + int Depth = ((Tic[5] >> 16) & 0x3fff) + 1; + + if (TextureType == TextureType.TwoD || TextureType == TextureType.OneD) + { + Depth = 1; + } GalImage Image = new GalImage( Width, Height, + Depth, TileWidth, BlockHeight, Layout, Format, + TextureType, XSource, YSource, ZSource, diff --git a/Ryujinx.Graphics/Texture/TextureType.cs b/Ryujinx.Graphics/Texture/TextureType.cs new file mode 100644 index 0000000000..2c095140a7 --- /dev/null +++ b/Ryujinx.Graphics/Texture/TextureType.cs @@ -0,0 +1,15 @@ +namespace Ryujinx.Graphics.Texture +{ + public enum TextureType + { + OneD = 0, + TwoD = 1, + ThreeD = 2, + CubeMap = 3, + OneDArray = 4, + TwoDArray = 5, + OneDBuffer = 6, + TwoDNoMipMap = 7, + CubeArray = 8, + } +} diff --git a/Ryujinx.Graphics/VDec/VideoDecoder.cs b/Ryujinx.Graphics/VDec/VideoDecoder.cs index 847392b0d9..05251c1463 100644 --- a/Ryujinx.Graphics/VDec/VideoDecoder.cs +++ b/Ryujinx.Graphics/VDec/VideoDecoder.cs @@ -216,10 +216,11 @@ namespace Ryujinx.Graphics.VDec GalImage Image = new GalImage( OutputConfig.SurfaceWidth, - OutputConfig.SurfaceHeight, 1, + OutputConfig.SurfaceHeight, 1, 1, OutputConfig.GobBlockHeight, GalMemoryLayout.BlockLinear, - GalImageFormat.RGBA8 | GalImageFormat.Unorm); + GalImageFormat.RGBA8 | GalImageFormat.Unorm, + TextureType.TwoD); ImageUtils.WriteTexture(Vmm, Image, Vmm.GetPhysicalAddress(OutputConfig.SurfaceLumaAddress), Frame.Data); } diff --git a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs index db04f47cd0..c24d42d08e 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs @@ -1,6 +1,8 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Memory; +using Ryujinx.Graphics.Texture; +using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Nv.NvGpuAS; using Ryujinx.HLE.HOS.Services.Nv.NvMap; @@ -415,9 +417,10 @@ namespace Ryujinx.HLE.HOS.Services.Android { image = new GalImage( fbWidth, - fbHeight, 1, BlockHeight, + fbHeight, 1, 1, BlockHeight, GalMemoryLayout.BlockLinear, - imageFormat); + imageFormat, + TextureType.TwoD); } context.Device.Gpu.ResourceManager.ClearPbCache();