diff --git a/Ryujinx.Graphics/Gal/GalImage.cs b/Ryujinx.Graphics/Gal/GalImage.cs index 5ee6a7f237..49dfcefc7a 100644 --- a/Ryujinx.Graphics/Gal/GalImage.cs +++ b/Ryujinx.Graphics/Gal/GalImage.cs @@ -6,7 +6,10 @@ namespace Ryujinx.Graphics.Gal { public int Width; public int Height; + + // FIXME: separate layer and depth public int Depth; + public int LayerCount; public int TileWidth; public int GobBlockHeight; public int GobBlockDepth; @@ -25,6 +28,7 @@ namespace Ryujinx.Graphics.Gal int Width, int Height, int Depth, + int LayerCount, int TileWidth, int GobBlockHeight, int GobBlockDepth, @@ -39,6 +43,7 @@ namespace Ryujinx.Graphics.Gal { this.Width = Width; this.Height = Height; + this.LayerCount = LayerCount; this.Depth = Depth; this.TileWidth = TileWidth; this.GobBlockHeight = GobBlockHeight; diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs index 75a97efc30..6f807270fe 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs @@ -82,7 +82,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL Type, IntPtr.Zero); break; - case TextureTarget.Texture2DArray: case TextureTarget.Texture3D: GL.TexImage3D( Target, @@ -96,6 +95,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL Type, IntPtr.Zero); break; + case TextureTarget.Texture2DArray: + GL.TexImage3D( + Target, + Level, + InternalFmt, + Image.Width, + Image.Height, + Image.LayerCount, + Border, + Format, + Type, + IntPtr.Zero); + break; case TextureTarget.TextureCubeMap: int FaceSize = ImageUtils.GetSize(Image) / Image.Depth; @@ -175,6 +187,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL case TextureTarget.TextureCubeMap: Span Array = new Span(Data); + // FIXME: wrong int FaceSize = ImageUtils.GetSize(Image) / Image.Depth; for (int Face = 0; Face < 6; Face++) @@ -197,7 +210,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL InternalFmt, Image.Width, Image.Height, - Image.Depth * 6, + Image.LayerCount * 6, Border, Data.Length, Data); @@ -257,7 +270,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL Type, Data); break; - case TextureTarget.Texture2DArray: case TextureTarget.Texture3D: GL.TexImage3D( Target, @@ -271,9 +283,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL Type, Data); break; + case TextureTarget.Texture2DArray: + GL.TexImage3D( + Target, + Level, + InternalFmt, + Image.Width, + Image.Height, + Image.LayerCount, + Border, + Format, + Type, + Data); + break; case TextureTarget.TextureCubeMap: Span Array = new Span(Data); + // FIXME: wrong int FaceSize = ImageUtils.GetSize(Image) / Image.Depth; for (int Face = 0; Face < 6; Face++) diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs index 87742ee9bd..9c236b848e 100644 --- a/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs +++ b/Ryujinx.Graphics/Graphics3d/NvGpuEngine2d.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Memory; using Ryujinx.Graphics.Texture; @@ -118,7 +119,7 @@ namespace Ryujinx.Graphics.Graphics3d GalImage SrcTexture = new GalImage( SrcWidth, SrcHeight, - SrcDepth, 1, + 1, SrcDepth, 1, SrcBlockHeight, 1, SrcLayout, SrcImgFormat, @@ -127,7 +128,7 @@ namespace Ryujinx.Graphics.Graphics3d GalImage DstTexture = new GalImage( DstWidth, DstHeight, - DstDepth, 1, + 1, DstDepth, 1, DstBlockHeight, 1, DstLayout, DstImgFormat, @@ -138,8 +139,7 @@ namespace Ryujinx.Graphics.Graphics3d long GetLayerOffset(GalImage Image, int Layer) { - // TODO: mip map - return (ImageUtils.GetGpuSize(Image) / Image.Depth) * Layer; + return (ImageUtils.GetGpuSize(Image) / Image.LayerCount) * Layer; } int SrcLayerIndex = -1; @@ -161,7 +161,7 @@ namespace Ryujinx.Graphics.Graphics3d if (IsSrcLayered && SrcLayerIndex == -1) { - for (int Layer = 0; Layer < SrcTexture.Depth; Layer++) + for (int Layer = 0; Layer < SrcTexture.LayerCount; Layer++) { Gpu.ResourceManager.SetTextureArrayLayer(SrcKey + GetLayerOffset(SrcTexture, Layer), Layer); } @@ -171,7 +171,7 @@ namespace Ryujinx.Graphics.Graphics3d if (IsDstLayered && DstLayerIndex == -1) { - for (int Layer = 0; Layer < DstTexture.Depth; Layer++) + for (int Layer = 0; Layer < DstTexture.LayerCount; Layer++) { Gpu.ResourceManager.SetTextureArrayLayer(DstKey + GetLayerOffset(DstTexture, Layer), Layer); } diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs index 14819eaba7..c05ad202b4 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, 1, GobBlockHeight, 1, Layout, Format, GalTextureTarget.TwoD); + GalImage Image = new GalImage(Width, Height, 1, 1, 1, GobBlockHeight, 1, Layout, Format, GalTextureTarget.TwoD); Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image); @@ -263,7 +263,7 @@ namespace Ryujinx.Graphics.Graphics3d GalImageFormat Format = ImageUtils.ConvertZeta((GalZetaFormat)ZetaFormat); // TODO: Support non 2D? - GalImage Image = new GalImage(Width, Height, 1, 1, GobBlockHeight, 1, Layout, Format, GalTextureTarget.TwoD); + GalImage Image = new GalImage(Width, Height, 1, 1, 1, GobBlockHeight, 1, Layout, Format, GalTextureTarget.TwoD); Gpu.ResourceManager.SendZetaBuffer(Vmm, Key, Image); } @@ -609,7 +609,7 @@ namespace Ryujinx.Graphics.Graphics3d { //FIXME: Some games like puyo puyo will use handles with the value 0. //This is a bug, most likely caused by sync issues. - return (0, default(GalImage), default(GalTextureSampler)); + //return (0, default(GalImage), default(GalTextureSampler)); } bool LinkedTsc = ReadRegisterBool(NvGpuEngine3dReg.LinkedTsc); diff --git a/Ryujinx.Graphics/Graphics3d/Texture/ISwizzle.cs b/Ryujinx.Graphics/Graphics3d/Texture/ISwizzle.cs index ddc4fe53ad..2e0e8aedd4 100644 --- a/Ryujinx.Graphics/Graphics3d/Texture/ISwizzle.cs +++ b/Ryujinx.Graphics/Graphics3d/Texture/ISwizzle.cs @@ -3,5 +3,11 @@ namespace Ryujinx.Graphics.Texture interface ISwizzle { int GetSwizzleOffset(int X, int Y, int Z); + + void SetMipLevel(int Level); + + int GetMipOffset(int Level); + + int GetImageSize(int MipsCount); } } \ No newline at end of file diff --git a/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs b/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs index a5d37accb7..3fb1822827 100644 --- a/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs +++ b/Ryujinx.Graphics/Graphics3d/Texture/ImageUtils.cs @@ -364,89 +364,9 @@ namespace Ryujinx.Graphics.Texture } } - // from envytools - private static readonly int GobSizeX = 64; - private static readonly int GobSizeY = 8; - private static readonly int GobSizeZ = 1; - - // https://github.com/mesa3d/mesa/blob/master/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c - // FIXME: the width is never set to anything, maybe there is other variants? - // TODO: miplevels - private static (int TileWidth, int TileHeight, int TileDepth) GetTileDimensions(GalImage Image) - { - (int Width, int Height, int Depth) = GetImageSizeInBlocks(Image); - - int TileWidth = 0; - int TileHeight = 0; - int TileDepth = 0; - - if (Height > 64) - { - TileHeight = 4; - } - else if (Height > 32) - { - TileHeight = 3; - } - else if (Height > 16) - { - TileHeight = 2; - } - else if (Height > 8) - { - TileHeight = 1; - } - - if (Image.TextureTarget == GalTextureTarget.ThreeD) - { - if (TileHeight > 2) - { - TileHeight = 2; - } - - if (Depth > 16 && TileDepth < 2) - { - TileDepth = 5; - } - else if (Depth > 8) - { - TileDepth = 4; - } - else if (Depth > 4) - { - TileDepth = 3; - } - else if (Depth > 2) - { - TileDepth = 2; - } - else if (Depth > 1) - { - TileDepth = 1; - } - } - - return (GobSizeX << TileWidth, GobSizeY << TileHeight, GobSizeZ << TileDepth); - } - public static int GetGpuSize(GalImage Image, bool forcePitch = false) { - ImageDescriptor Desc = GetImageDescriptor(Image.Format); - - if (Image.Layout == GalMemoryLayout.Pitch || forcePitch) - { - // TODO: check this - return Image.Width * Image.Height * Image.Depth * Desc.BytesPerPixel; - } - - (int TileWidth, int TileHeight, int TileDepth) = GetTileDimensions(Image); - (int BlockX, int BlockY, int _) = GetImageSizeInBlocks(Image); - - int Pitch = BitUtils.AlignUp(BlockX * Desc.BytesPerPixel, TileWidth); - int Height = BitUtils.AlignUp(BlockY, TileHeight); - int Depth = BitUtils.AlignUp(Image.Depth, TileDepth); - - return BitUtils.AlignUp(Pitch * Height * Depth, (GobSizeX * GobSizeY) << (TileWidth + TileHeight + TileDepth)); + return TextureHelper.GetSwizzle(Image).GetImageSize(Image.MaxMipmapLevel) * Image.LayerCount; } public static int GetPitch(GalImageFormat Format, int Width) diff --git a/Ryujinx.Graphics/Graphics3d/Texture/LinearSwizzle.cs b/Ryujinx.Graphics/Graphics3d/Texture/LinearSwizzle.cs index ffd9b472b7..c09224c6ae 100644 --- a/Ryujinx.Graphics/Graphics3d/Texture/LinearSwizzle.cs +++ b/Ryujinx.Graphics/Graphics3d/Texture/LinearSwizzle.cs @@ -1,3 +1,5 @@ +using System; + namespace Ryujinx.Graphics.Texture { class LinearSwizzle : ISwizzle @@ -14,6 +16,23 @@ namespace Ryujinx.Graphics.Texture SliceSize = Width * Height * Bpp; } + public void SetMipLevel(int Level) + { + throw new NotImplementedException(); + } + + public int GetMipOffset(int Level) + { + throw new NotImplementedException(); + } + + public int GetImageSize(int MipsCount) + { + if (MipsCount == 1) + return SliceSize; + throw new NotImplementedException(); + } + public int GetSwizzleOffset(int X, int Y, int Z) { return Z * SliceSize + X * Bpp + Y * Pitch; diff --git a/Ryujinx.Graphics/Graphics3d/Texture/TextureFactory.cs b/Ryujinx.Graphics/Graphics3d/Texture/TextureFactory.cs index 61409823f0..feafcedb44 100644 --- a/Ryujinx.Graphics/Graphics3d/Texture/TextureFactory.cs +++ b/Ryujinx.Graphics/Graphics3d/Texture/TextureFactory.cs @@ -47,6 +47,15 @@ namespace Ryujinx.Graphics.Texture int Height = ((Tic[5] >> 0) & 0xffff) + 1; int Depth = ((Tic[5] >> 16) & 0x3fff) + 1; + int LayoutCount = 1; + + // TODO: check this + if (ImageUtils.IsArray(TextureTarget)) + { + LayoutCount = Depth; + Depth = 1; + } + if (TextureTarget == GalTextureTarget.OneD) { Height = 1; @@ -58,6 +67,7 @@ namespace Ryujinx.Graphics.Texture } else if (TextureTarget == GalTextureTarget.CubeMap) { + // TODO: WRONG Depth = 6; } @@ -65,6 +75,7 @@ namespace Ryujinx.Graphics.Texture Width, Height, Depth, + LayoutCount, TileWidth, GobBlockHeight, GobBlockDepth, diff --git a/Ryujinx.Graphics/VDec/VideoDecoder.cs b/Ryujinx.Graphics/VDec/VideoDecoder.cs index 7d3a890dfe..be53b1a02c 100644 --- a/Ryujinx.Graphics/VDec/VideoDecoder.cs +++ b/Ryujinx.Graphics/VDec/VideoDecoder.cs @@ -216,7 +216,7 @@ namespace Ryujinx.Graphics.VDec GalImage Image = new GalImage( OutputConfig.SurfaceWidth, - OutputConfig.SurfaceHeight, 1, 1, + OutputConfig.SurfaceHeight, 1, 1, 1, OutputConfig.GobBlockHeight, 1, GalMemoryLayout.BlockLinear, GalImageFormat.RGBA8 | GalImageFormat.Unorm, diff --git a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs index 37f0c9e09f..dbf255beee 100644 --- a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs +++ b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs @@ -416,7 +416,7 @@ namespace Ryujinx.HLE.HOS.Services.Android { image = new GalImage( fbWidth, - fbHeight, 1, 1, BlockHeight, 1, + fbHeight, 1, 1, 1, BlockHeight, 1, GalMemoryLayout.BlockLinear, imageFormat, GalTextureTarget.TwoD);