diff --git a/Ryujinx.Graphics/Gal/GalImage.cs b/Ryujinx.Graphics/Gal/GalImage.cs index dc6f02e04..e9691b67b 100644 --- a/Ryujinx.Graphics/Gal/GalImage.cs +++ b/Ryujinx.Graphics/Gal/GalImage.cs @@ -4,8 +4,10 @@ namespace Ryujinx.Graphics.Gal { public int Width; public int Height; + public int Depth; public GalImageFormat Format; + public GalImageTarget Target; public GalTextureSource XSource; public GalTextureSource YSource; @@ -15,7 +17,9 @@ namespace Ryujinx.Graphics.Gal public GalImage( int Width, int Height, + int Depth, GalImageFormat Format, + GalImageTarget Target, GalTextureSource XSource = GalTextureSource.Red, GalTextureSource YSource = GalTextureSource.Green, GalTextureSource ZSource = GalTextureSource.Blue, @@ -23,7 +27,9 @@ namespace Ryujinx.Graphics.Gal { this.Width = Width; this.Height = Height; + this.Depth = Depth; this.Format = Format; + this.Target = Target; this.XSource = XSource; this.YSource = YSource; this.ZSource = ZSource; diff --git a/Ryujinx.Graphics/Gal/GalImageType.cs b/Ryujinx.Graphics/Gal/GalImageType.cs new file mode 100644 index 000000000..fae7f8c87 --- /dev/null +++ b/Ryujinx.Graphics/Gal/GalImageType.cs @@ -0,0 +1,15 @@ +namespace Ryujinx.Graphics.Gal +{ + public enum GalImageTarget + { + _1d = 0, + _2d = 1, + _3d = 2, + CubeMap = 3, + _1dArray = 4, + _2dArray = 5, + _1dBuffer = 6, + _2dNoMimap = 7, //GL_TEXTURE_RECTANGLE? + CubeArray = 8, + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/IGalTexture.cs b/Ryujinx.Graphics/Gal/IGalTexture.cs index 292f59efa..ea9301e54 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); - void SetSampler(GalTextureSampler Sampler); + void SetSampler(long Key, GalTextureSampler Sampler); } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs index 74f18dcd3..e700be05d 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs @@ -34,13 +34,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL public ImageHandler(int Handle, GalImage Image) { this.Handle = Handle; - - this.Image = Image; + this.Image = Image; } public void EnsureSetup(GalImage Image) { - if (Width != Image.Width || + if (Width != Image.Width || Height != Image.Height || Format != Image.Format || !Initialized) @@ -48,7 +47,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL (PixelInternalFormat InternalFormat, PixelFormat PixelFormat, PixelType PixelType) = OGLEnumConverter.GetImageFormat(Image.Format); - GL.BindTexture(TextureTarget.Texture2D, Handle); + TextureTarget Target = OGLEnumConverter.GetImageTarget(Image.Target); + + GL.BindTexture(Target, Handle); if (Initialized) { @@ -72,7 +73,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.BufferData(BufferTarget.PixelPackBuffer, CurrentSize, IntPtr.Zero, BufferUsageHint.StreamCopy); } - GL.GetTexImage(TextureTarget.Texture2D, 0, this.PixelFormat, this.PixelType, IntPtr.Zero); + GL.GetTexImage(Target, 0, this.PixelFormat, this.PixelType, IntPtr.Zero); GL.DeleteTexture(Handle); @@ -84,22 +85,44 @@ namespace Ryujinx.Graphics.Gal.OpenGL const int MinFilter = (int)TextureMinFilter.Linear; const int MagFilter = (int)TextureMagFilter.Linear; - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter); + GL.TexParameter(Target, TextureParameterName.TextureMinFilter, MinFilter); + GL.TexParameter(Target, TextureParameterName.TextureMagFilter, MagFilter); const int Level = 0; const int Border = 0; - GL.TexImage2D( - TextureTarget.Texture2D, - Level, - InternalFormat, - Image.Width, - Image.Height, - Border, - PixelFormat, - PixelType, - IntPtr.Zero); + switch (Target) + { + case TextureTarget.Texture2D: + GL.TexImage2D( + Target, + Level, + InternalFormat, + Image.Width, + Image.Height, + Border, + PixelFormat, + PixelType, + IntPtr.Zero); + break; + + case TextureTarget.Texture2DArray: + GL.TexImage3D( + Target, + Level, + InternalFormat, + Image.Width, + Image.Height, + Image.Depth, + Border, + PixelFormat, + PixelType, + IntPtr.Zero); + break; + + default: + throw new NotImplementedException(Target.ToString()); + } if (Initialized) { diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs index e04a59d44..9fb3c4392 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs @@ -299,5 +299,17 @@ namespace Ryujinx.Graphics.Gal.OpenGL throw new ArgumentException(nameof(BlendFactor)); } + + public static TextureTarget GetImageTarget(GalImageTarget Target) + { + switch (Target) + { + case GalImageTarget._2d: return TextureTarget.Texture2D; + case GalImageTarget._2dArray: return TextureTarget.Texture2DArray; + case GalImageTarget.CubeMap: return TextureTarget.TextureCubeMap; + } + + throw new NotImplementedException(Target.ToString()); + } } } diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs index 12239c4f0..dc85f8fae 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs @@ -173,7 +173,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL RawTex = new ImageHandler(); } - RawTex.EnsureSetup(new GalImage(Width, Height, RawFormat)); + RawTex.EnsureSetup(new GalImage(Width, Height, 1, RawFormat, GalImageTarget._2d)); GL.BindTexture(TextureTarget.Texture2D, RawTex.Handle); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs index e4d4bd648..619a8368e 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs @@ -34,7 +34,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length); - GL.BindTexture(TextureTarget.Texture2D, Handle); + TextureTarget Target = OGLEnumConverter.GetImageTarget(Image.Target); + + GL.BindTexture(Target, Handle); const int Level = 0; //TODO: Support mipmap textures. const int Border = 0; @@ -43,21 +45,67 @@ 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: + GL.CompressedTexImage3D( + Target, + Level, + InternalFmt, + Image.Width, + Image.Height, + Image.Depth, + Border, + Data.Length, + Data); + break; + + case TextureTarget.TextureCubeMap: + { + int FaceSize = Data.Length / 6; + + for (int i = 0; i < 6; i++) + { + unsafe + { + fixed (byte* DataPtr = Data) + { + GL.CompressedTexImage2D( + TextureTarget.TextureCubeMapPositiveX + i, + Level, + InternalFmt, + Image.Width, + Image.Height, + Border, + FaceSize, + (IntPtr)(DataPtr + FaceSize * i)); + } + } + } + break; + } + + default: + throw new NotImplementedException(Target.ToString()); + } } else { if (Image.Format >= GalImageFormat.ASTC_BEGIN && Image.Format <= GalImageFormat.ASTC_END) { - int TextureBlockWidth = GetAstcBlockWidth(Image.Format); + int TextureBlockWidth = GetAstcBlockWidth(Image.Format); int TextureBlockHeight = GetAstcBlockHeight(Image.Format); Data = ASTCDecoder.DecodeToRGBA8888( @@ -72,16 +120,64 @@ namespace Ryujinx.Graphics.Gal.OpenGL (PixelInternalFormat InternalFormat, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format); - GL.TexImage2D( - TextureTarget.Texture2D, - Level, - InternalFormat, - Image.Width, - Image.Height, - Border, - Format, - Type, - Data); + switch (Target) + { + case TextureTarget.Texture2D: + GL.TexImage2D( + Target, + Level, + InternalFormat, + Image.Width, + Image.Height, + Border, + Format, + Type, + Data); + break; + + case TextureTarget.TextureCubeMap: + { + long FaceSize = Data.LongLength / 6; + + for (int i = 0; i < 6; i++) + { + unsafe + { + fixed (byte* DataPtr = Data) + { + GL.TexImage2D( + TextureTarget.TextureCubeMapPositiveX + i, + Level, + InternalFormat, + Image.Width, + Image.Height, + Border, + Format, + Type, + (IntPtr)(DataPtr + FaceSize * i)); + } + } + } + break; + } + + case TextureTarget.Texture2DArray: + GL.TexImage3D( + Target, + Level, + InternalFormat, + Image.Width, + Image.Height, + Image.Depth, + Border, + Format, + Type, + Data); + break; + + default: + throw new NotImplementedException(Target.ToString()); + } } int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource); @@ -89,10 +185,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource); int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, SwizzleB); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA); + GL.TexParameter(Target, TextureParameterName.TextureSwizzleR, SwizzleR); + GL.TexParameter(Target, TextureParameterName.TextureSwizzleG, SwizzleG); + GL.TexParameter(Target, TextureParameterName.TextureSwizzleB, SwizzleB); + GL.TexParameter(Target, TextureParameterName.TextureSwizzleA, SwizzleA); } public void CreateFb(long Key, long Size, GalImage Image) @@ -186,25 +282,34 @@ namespace Ryujinx.Graphics.Gal.OpenGL { if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage)) { + TextureTarget Target = OGLEnumConverter.GetImageTarget(CachedImage.Image.Target); + GL.ActiveTexture(TextureUnit.Texture0 + Index); - GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle); + GL.BindTexture(Target, CachedImage.Handle); } } - public void SetSampler(GalTextureSampler Sampler) + public void SetSampler(long Key, GalTextureSampler Sampler) { + if (!TextureCache.TryGetValue(Key, out ImageHandler CachedImage)) + { + return; + } + + TextureTarget Target = OGLEnumConverter.GetImageTarget(CachedImage.Image.Target); + int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU); int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV); 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); + GL.TexParameter(Target, TextureParameterName.TextureWrapS, WrapS); + GL.TexParameter(Target, TextureParameterName.TextureWrapT, WrapT); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter); + GL.TexParameter(Target, TextureParameterName.TextureMinFilter, MinFilter); + GL.TexParameter(Target, TextureParameterName.TextureMagFilter, MagFilter); float[] Color = new float[] { @@ -214,7 +319,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL Sampler.BorderColor.Alpha }; - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color); + GL.TexParameter(Target, TextureParameterName.TextureBorderColor, Color); } private static bool IsCompressedTextureFormat(GalImageFormat Format) diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index c22a282dc..9dd6cb91d 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -63,6 +63,8 @@ namespace Ryujinx.Graphics.Gal.Shader private Dictionary m_Gprs; private Dictionary m_Preds; + private Dictionary m_TextureTypes; + public IReadOnlyDictionary CbTextures => m_CbTextures; public IReadOnlyDictionary Textures => m_Textures; @@ -75,6 +77,8 @@ namespace Ryujinx.Graphics.Gal.Shader public IReadOnlyDictionary Gprs => m_Gprs; public IReadOnlyDictionary Preds => m_Preds; + public IReadOnlyDictionary TextureTypes => m_TextureTypes; + public GalShaderType ShaderType { get; private set; } private GlslDecl(GalShaderType ShaderType) @@ -92,6 +96,8 @@ namespace Ryujinx.Graphics.Gal.Shader m_Gprs = new Dictionary(); m_Preds = new Dictionary(); + + m_TextureTypes = new Dictionary(); } public GlslDecl(ShaderIrBlock[] Blocks, GalShaderType ShaderType, ShaderHeader Header) @@ -221,16 +227,26 @@ namespace Ryujinx.Graphics.Gal.Shader Op.Inst == ShaderIrInst.Texs || Op.Inst == ShaderIrInst.Txlf) { - int Handle = ((ShaderIrOperImm)Op.OperandC).Value; + ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData; + + Traverse(Nodes, Op, Meta.Index); + + int Handle = ((ShaderIrOperImm)Meta.Index).Value; int Index = Handle - TexStartIndex; string Name = StagePrefix + TextureName + Index; m_Textures.TryAdd(Handle, new ShaderDeclInfo(Name, Handle)); + + m_TextureTypes.TryAdd(Handle, Meta.Type); } else if (Op.Inst == ShaderIrInst.Texb) { + ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData; + + Traverse(Nodes, Op, Meta.Index); + ShaderIrNode HandleSrc = null; int Index = Array.IndexOf(Nodes, Parent) - 1; @@ -241,7 +257,7 @@ namespace Ryujinx.Graphics.Gal.Shader if (Curr is ShaderIrAsg Asg && Asg.Dst is ShaderIrOperGpr Gpr) { - if (Gpr.Index == ((ShaderIrOperGpr)Op.OperandC).Index) + if (Gpr.Index == ((ShaderIrOperGpr)Meta.Index).Index) { HandleSrc = Asg.Src; @@ -255,6 +271,8 @@ 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)); + + //TODO: Add m_CbTextures to texture types } else { diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index 984684f16..0a1be5e41 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -221,7 +221,16 @@ namespace Ryujinx.Graphics.Gal.Shader SB.AppendLine("uniform sampler2D " + DeclInfo.Name + ";"); } - PrintDecls(Decl.Textures, "uniform sampler2D"); + foreach (ShaderDeclInfo DeclInfo in Decl.Textures.Values.OrderBy(DeclKeySelector)) + { + ShaderTextureType Type = Decl.TextureTypes[DeclInfo.Index]; + + string TypeName = GetSamplerName(Type); + + SB.AppendLine("uniform " + TypeName + " " + DeclInfo.Name + ";"); + } + + SB.AppendLine(); } private IEnumerable IterateCbTextures() @@ -1188,9 +1197,9 @@ namespace Ryujinx.Graphics.Gal.Shader private string GetTexSamplerName(ShaderIrOp Op) { - ShaderIrOperImm Node = (ShaderIrOperImm)Op.OperandC; + ShaderIrNode Node = ((ShaderIrMetaTex)Op.MetaData).Index; - int Handle = ((ShaderIrOperImm)Op.OperandC).Value; + int Handle = ((ShaderIrOperImm)Node).Value; if (!Decl.Textures.TryGetValue(Handle, out ShaderDeclInfo DeclInfo)) { @@ -1202,14 +1211,32 @@ namespace Ryujinx.Graphics.Gal.Shader private string GetTexSamplerCoords(ShaderIrOp Op) { - return "vec2(" + GetOperExpr(Op, Op.OperandA) + ", " + - GetOperExpr(Op, Op.OperandB) + ")"; + if (Op.OperandC != null) + { + return "vec3(" + GetOperExpr(Op, Op.OperandA) + ", " + + GetOperExpr(Op, Op.OperandB) + ", " + + GetOperExpr(Op, Op.OperandC) + ")"; + } + else + { + return "vec2(" + GetOperExpr(Op, Op.OperandA) + ", " + + GetOperExpr(Op, Op.OperandB) + ")"; + } } private string GetITexSamplerCoords(ShaderIrOp Op) { - return "ivec2(" + GetOperExpr(Op, Op.OperandA) + ", " + - GetOperExpr(Op, Op.OperandB) + ")"; + if (Op.OperandC != null) + { + return "ivec3(" + GetOperExpr(Op, Op.OperandA) + ", " + + GetOperExpr(Op, Op.OperandB) + ", " + + GetOperExpr(Op, Op.OperandC) + ")"; + } + else + { + return "ivec2(" + GetOperExpr(Op, Op.OperandA) + ", " + + GetOperExpr(Op, Op.OperandB) + ")"; + } } private string GetOperExpr(ShaderIrOp Op, ShaderIrNode Oper) @@ -1351,5 +1378,17 @@ namespace Ryujinx.Graphics.Gal.Shader throw new ArgumentException(nameof(Node)); } + + private static string GetSamplerName(ShaderTextureType Type) + { + switch (Type) + { + case ShaderTextureType._2d: return "sampler2D"; + case ShaderTextureType._2dArray: return "sampler2DArray"; + case ShaderTextureType.Cube: return "samplerCube"; + } + + throw new NotImplementedException(Type.ToString()); + } } } diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs index a183b0c69..aa8c17cb4 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs @@ -31,13 +31,28 @@ namespace Ryujinx.Graphics.Gal.Shader { RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ } }; + private static ShaderTextureType[] TexsTypes = new ShaderTextureType[] + { + ShaderTextureType._1d, + ShaderTextureType._2d, + ShaderTextureType._2d, + ShaderTextureType._2d, + ShaderTextureType._2d, + ShaderTextureType._2d, + ShaderTextureType._2d, + ShaderTextureType._2dArray, + ShaderTextureType._2dArray, + ShaderTextureType._2dArray, + ShaderTextureType._3d, + ShaderTextureType._3d, + ShaderTextureType.Cube, + ShaderTextureType.Cube, + }; + public static void Ld_A(ShaderIrBlock Block, long OpCode) { ShaderIrNode[] Opers = GetOperAbuf20(OpCode); - //Used by GS - ShaderIrOperGpr Vertex = GetOperGpr39(OpCode); - int Index = 0; foreach (ShaderIrNode OperA in Opers) @@ -118,15 +133,15 @@ namespace Ryujinx.Graphics.Gal.Shader ShaderIrNode OperD = GetOperGpr0(OpCode); ShaderIrNode OperA = GetOperGpr8(OpCode); + ShaderIrNode TextureIndex = GetOperImm13_36(OpCode); + ShaderTexqInfo Info = (ShaderTexqInfo)((OpCode >> 22) & 0x1f); - ShaderIrMetaTexq Meta0 = new ShaderIrMetaTexq(Info, 0); - ShaderIrMetaTexq Meta1 = new ShaderIrMetaTexq(Info, 1); + ShaderIrMetaTexq Meta0 = new ShaderIrMetaTexq(Info, ShaderTextureType._2d, TextureIndex, 0); + ShaderIrMetaTexq Meta1 = new ShaderIrMetaTexq(Info, ShaderTextureType._2d, TextureIndex, 1); - ShaderIrNode OperC = GetOperImm13_36(OpCode); - - ShaderIrOp Op0 = new ShaderIrOp(ShaderIrInst.Texq, OperA, null, OperC, Meta0); - ShaderIrOp Op1 = new ShaderIrOp(ShaderIrInst.Texq, OperA, null, OperC, Meta1); + ShaderIrOp Op0 = new ShaderIrOp(ShaderIrInst.Texq, OperA, null, null, Meta0); + ShaderIrOp Op1 = new ShaderIrOp(ShaderIrInst.Texq, OperA, null, null, Meta1); Block.AddNode(GetPredNode(new ShaderIrAsg(OperD, Op0), OpCode)); Block.AddNode(GetPredNode(new ShaderIrAsg(OperA, Op1), OpCode)); //Is this right? @@ -161,7 +176,7 @@ namespace Ryujinx.Graphics.Gal.Shader int ChMask = (int)(OpCode >> 31) & 0xf; - ShaderIrNode OperC = GprHandle + ShaderIrNode TextureIndex = GprHandle ? (ShaderIrNode)GetOperGpr20 (OpCode) : (ShaderIrNode)GetOperImm13_36(OpCode); @@ -171,9 +186,9 @@ namespace Ryujinx.Graphics.Gal.Shader { ShaderIrOperGpr Dst = new ShaderIrOperGpr(TempRegStart + Ch); - ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch); + ShaderIrMetaTex Meta = new ShaderIrMetaTex(ShaderTextureType._2d, TextureIndex, Ch); - ShaderIrOp Op = new ShaderIrOp(Inst, Coords[0], Coords[1], OperC, Meta); + ShaderIrOp Op = new ShaderIrOp(Inst, Coords[0], Coords[1], null, Meta); Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Op), OpCode)); } @@ -214,10 +229,7 @@ namespace Ryujinx.Graphics.Gal.Shader private static void EmitTexs(ShaderIrBlock Block, long OpCode, ShaderIrInst Inst) { - //TODO: Support other formats. - ShaderIrNode OperA = GetOperGpr8 (OpCode); - ShaderIrNode OperB = GetOperGpr20 (OpCode); - ShaderIrNode OperC = GetOperImm13_36(OpCode); + ShaderIrNode TextureIndex = GetOperImm13_36(OpCode); int LutIndex; @@ -233,11 +245,44 @@ namespace Ryujinx.Graphics.Gal.Shader int ChMask = MaskLut[LutIndex, (OpCode >> 50) & 7]; + long TypeIndex = (OpCode >> 53) & 0xf; + + ShaderTextureType Type = TexsTypes[TypeIndex]; + + ShaderIrNode OperA = null; + ShaderIrNode OperB = null; + ShaderIrNode OperC = null; + + switch (Type) + { + case ShaderTextureType._2d: + OperA = GetOperGpr8 (OpCode); + OperB = GetOperGpr20(OpCode); + break; + + //Unsure about this layout + case ShaderTextureType._2dArray: + OperA = GetOperGpr8 (OpCode) + 1; + OperB = GetOperGpr20(OpCode); + OperC = GetOperGpr8 (OpCode); + break; + + //Unsure about this layout + case ShaderTextureType.Cube: + OperA = GetOperGpr8 (OpCode); + OperB = GetOperGpr8 (OpCode) + 1; + OperC = GetOperGpr20(OpCode); + break; + + default: + throw new NotImplementedException(Type.ToString()); + } + for (int Ch = 0; Ch < 4; Ch++) { ShaderIrOperGpr Dst = new ShaderIrOperGpr(TempRegStart + Ch); - ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch); + ShaderIrMetaTex Meta = new ShaderIrMetaTex(Type, TextureIndex, Ch); ShaderIrOp Op = new ShaderIrOp(Inst, OperA, OperB, OperC, Meta); diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs index 82f3bb774..3ff8ab39e 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs @@ -2,11 +2,17 @@ namespace Ryujinx.Graphics.Gal.Shader { class ShaderIrMetaTex : ShaderIrMeta { + public ShaderTextureType Type { get; private set; } + + public ShaderIrNode Index { get; private set; } + public int Elem { get; private set; } - public ShaderIrMetaTex(int Elem) + public ShaderIrMetaTex(ShaderTextureType Type, ShaderIrNode Index, int Elem) { - this.Elem = Elem; + this.Type = Type; + this.Index = Index; + this.Elem = Elem; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTexq.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTexq.cs index 92871137f..db6e8f11d 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTexq.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTexq.cs @@ -1,15 +1,13 @@ namespace Ryujinx.Graphics.Gal.Shader { - class ShaderIrMetaTexq : ShaderIrMeta + class ShaderIrMetaTexq : ShaderIrMetaTex { public ShaderTexqInfo Info { get; private set; } - public int Elem { get; private set; } - - public ShaderIrMetaTexq(ShaderTexqInfo Info, int Elem) + public ShaderIrMetaTexq(ShaderTexqInfo Info, ShaderTextureType Type, ShaderIrNode Index, int Elem) + : base(Type, Index, Elem) { this.Info = Info; - this.Elem = Elem; } } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs index 9dd196e69..eddcf9fb4 100644 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs +++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs @@ -15,6 +15,11 @@ namespace Ryujinx.Graphics.Gal.Shader this.Index = Index; } + public static ShaderIrOperGpr operator+(ShaderIrOperGpr Gpr, int PlusIndex) + { + return new ShaderIrOperGpr(Gpr.Index + PlusIndex); + } + public static ShaderIrOperGpr MakeTemporary(int Index = 0) { return new ShaderIrOperGpr(0x100 + Index); diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderTextureType.cs b/Ryujinx.Graphics/Gal/Shader/ShaderTextureType.cs new file mode 100644 index 000000000..27cab3080 --- /dev/null +++ b/Ryujinx.Graphics/Gal/Shader/ShaderTextureType.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.Graphics.Gal.Shader +{ + enum ShaderTextureType + { + _1d, + _2d, + _2dArray, + _3d, + Cube + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs index 2010e43bd..0d35da22d 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs @@ -202,7 +202,7 @@ namespace Ryujinx.HLE.Gpu.Engines GalImageFormat ImageFormat = ImageFormatConverter.ConvertFrameBuffer((GalFrameBufferFormat)Format); - GalImage Image = new GalImage(Width, Height, ImageFormat); + GalImage Image = new GalImage(Width, Height, 1, ImageFormat, GalImageTarget._2d); long Size = TextureHelper.GetTextureSize(Image); @@ -234,7 +234,7 @@ namespace Ryujinx.HLE.Gpu.Engines GalImageFormat ImageFormat = ImageFormatConverter.ConvertZeta((GalZetaFormat)Format); - GalImage Image = new GalImage(Width, Height, ImageFormat); + GalImage Image = new GalImage(Width, Height, 1, ImageFormat, GalImageTarget._2d); long Size = TextureHelper.GetTextureSize(Image); @@ -549,7 +549,7 @@ namespace Ryujinx.HLE.Gpu.Engines Gpu.Renderer.Texture.Bind(Key, TexIndex); } - Gpu.Renderer.Texture.SetSampler(Sampler); + Gpu.Renderer.Texture.SetSampler(Key, Sampler); } private void UploadConstBuffers(NvGpuVmm Vmm, GalPipelineState State, long[] Keys) diff --git a/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs b/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs index 0ef33d3b7..2aad803a7 100644 --- a/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs +++ b/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs @@ -24,11 +24,16 @@ namespace Ryujinx.HLE.Gpu.Texture int Width = (Tic[4] & 0xffff) + 1; int Height = (Tic[5] & 0xffff) + 1; + int Depth = ((Tic[5] >> 16) & 0x7fff) + 1; + + GalImageTarget Target = (GalImageTarget)((Tic[4] >> 23) & 0xf); return new GalImage( Width, Height, + Depth, Format, + Target, XSource, YSource, ZSource,