diff --git a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs index d3dfffea75..4aa807f1c7 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs @@ -46,8 +46,21 @@ namespace Ryujinx.Graphics.Gal.OpenGL return; } - (PixelInternalFormat InternalFormat, PixelFormat PixelFormat, PixelType PixelType) = - OGLEnumConverter.GetImageFormat(NewImage.Format); + PixelInternalFormat InternalFmt; + PixelFormat PixelFormat; + PixelType PixelType; + + if (ImageTable.IsCompressed(NewImage.Format)) + { + InternalFmt = (PixelInternalFormat)OGLEnumConverter.GetCompressedImageFormat(NewImage.Format); + + PixelFormat = default(PixelFormat); + PixelType = default(PixelType); + } + else + { + (InternalFmt, PixelFormat, PixelType) = OGLEnumConverter.GetImageFormat(NewImage.Format); + } GL.BindTexture(TextureTarget.Texture2D, Handle); @@ -58,8 +71,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL CopyBuffer = GL.GenBuffer(); } - int CurrentSize = Math.Max(ImageTable.GetImageSize(NewImage), - ImageTable.GetImageSize(Image)); + int CurrentSize = Math.Max(ImageTable.GetSize(NewImage), + ImageTable.GetSize(Image)); GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyBuffer); GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyBuffer); @@ -71,7 +84,14 @@ 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); + if (ImageTable.IsCompressed(Image.Format)) + { + GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, IntPtr.Zero); + } + else + { + GL.GetTexImage(TextureTarget.Texture2D, 0, this.PixelFormat, this.PixelType, IntPtr.Zero); + } GL.DeleteTexture(Handle); @@ -89,16 +109,33 @@ namespace Ryujinx.Graphics.Gal.OpenGL const int Level = 0; const int Border = 0; - GL.TexImage2D( - TextureTarget.Texture2D, - Level, - InternalFormat, - NewImage.Width, - NewImage.Height, - Border, - PixelFormat, - PixelType, - IntPtr.Zero); + if (ImageTable.IsCompressed(NewImage.Format)) + { + Console.WriteLine("Hit"); + + GL.CompressedTexImage2D( + TextureTarget.Texture2D, + Level, + (InternalFormat)InternalFmt, + NewImage.Width, + NewImage.Height, + Border, + ImageTable.GetSize(NewImage), + IntPtr.Zero); + } + else + { + GL.TexImage2D( + TextureTarget.Texture2D, + Level, + InternalFmt, + NewImage.Width, + NewImage.Height, + Border, + PixelFormat, + PixelType, + IntPtr.Zero); + } if (Initialized) { @@ -108,7 +145,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL Image = NewImage; - this.InternalFormat = InternalFormat; + this.InternalFormat = InternalFmt; this.PixelFormat = PixelFormat; this.PixelType = PixelType; diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs index a169e75d21..b52e2b312d 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs @@ -380,7 +380,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL { if (Texture.TryGetImage(Key, out ImageHandler Tex)) { - byte[] Data = new byte[ImageTable.GetImageSize(Tex.Image)]; + byte[] Data = new byte[ImageTable.GetSize(Tex.Image)]; GL.BindTexture(TextureTarget.Texture2D, Tex.Handle); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs index e87c35755e..6ac4b5e51d 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs @@ -39,7 +39,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL const int Level = 0; //TODO: Support mipmap textures. const int Border = 0; - if (IsCompressedTextureFormat(Image.Format)) + GalImageFormat TypeLess = Image.Format & GalImageFormat.FormatMask; + + bool IsASTC = TypeLess >= GalImageFormat.ASTC_BEGIN && TypeLess <= GalImageFormat.ASTC_END; + + if (ImageTable.IsCompressed(Image.Format) && !IsASTC) { InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format); @@ -55,10 +59,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL } else { - GalImageFormat TypeLess = Image.Format & GalImageFormat.FormatMask; - //TODO: Use KHR_texture_compression_astc_hdr when available - if (TypeLess >= GalImageFormat.ASTC_BEGIN && TypeLess <= GalImageFormat.ASTC_END) + if (IsASTC) { int TextureBlockWidth = GetAstcBlockWidth(Image.Format); int TextureBlockHeight = GetAstcBlockHeight(Image.Format); @@ -229,23 +231,5 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color); } - - private static bool IsCompressedTextureFormat(GalImageFormat Format) - { - switch (Format & GalImageFormat.FormatMask) - { - case GalImageFormat.BC6H_UF16: - case GalImageFormat.BC6H_SF16: - case GalImageFormat.BC7: - case GalImageFormat.BC1_RGBA: - case GalImageFormat.BC2: - case GalImageFormat.BC3: - case GalImageFormat.BC4: - case GalImageFormat.BC5: - return true; - } - - return false; - } } } diff --git a/Ryujinx.Graphics/NvGpuEngine3d.cs b/Ryujinx.Graphics/NvGpuEngine3d.cs index cb3485c0f3..701c51c30b 100644 --- a/Ryujinx.Graphics/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/NvGpuEngine3d.cs @@ -205,7 +205,7 @@ namespace Ryujinx.Graphics GalImage Image = new GalImage(Width, Height, ImageFormat); - long Size = ImageTable.GetImageSize(Image); + long Size = ImageTable.GetSize(Image); Gpu.Renderer.Texture.CreateFb(Key, Size, Image); @@ -238,7 +238,7 @@ namespace Ryujinx.Graphics GalImage Image = new GalImage(Width, Height, ImageFormat); - long Size = ImageTable.GetImageSize(Image); + long Size = ImageTable.GetSize(Image); Gpu.Renderer.Texture.CreateFb(Key, Size, Image); @@ -528,7 +528,7 @@ namespace Ryujinx.Graphics { GalImage NewImage = TextureFactory.MakeTexture(Vmm, TicPosition); - long Size = (uint)ImageTable.GetImageSize(NewImage); + long Size = (uint)ImageTable.GetSize(NewImage); bool HasCachedTexture = false; diff --git a/Ryujinx.Graphics/Texture/ImageTable.cs b/Ryujinx.Graphics/Texture/ImageTable.cs index 83d85e8efe..311e89f3a3 100644 --- a/Ryujinx.Graphics/Texture/ImageTable.cs +++ b/Ryujinx.Graphics/Texture/ImageTable.cs @@ -14,16 +14,20 @@ namespace Ryujinx.Graphics.Texture public bool HasDepth; public bool HasStencil; + public bool Compressed; + public ImageDescriptor( TextureReaderDelegate Reader, bool HasColor, bool HasDepth, - bool HasStencil) + bool HasStencil, + bool Compressed) { this.Reader = Reader; this.HasColor = HasColor; this.HasDepth = HasDepth; this.HasStencil = HasStencil; + this.Compressed = Compressed; } } @@ -79,50 +83,51 @@ namespace Ryujinx.Graphics.Texture }; private static readonly Dictionary s_ImageTable = - new Dictionary() + new Dictionary() { - { GalImageFormat.R32G32B32A32, new ImageDescriptor(TextureReader.Read16Bpp, true, false, false) }, - { GalImageFormat.R16G16B16A16, new ImageDescriptor(TextureReader.Read8Bpp, true, false, false) }, - { GalImageFormat.R32G32, new ImageDescriptor(TextureReader.Read8Bpp, true, false, false) }, - { GalImageFormat.A8B8G8R8, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false) }, - { GalImageFormat.A2B10G10R10, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false) }, - { GalImageFormat.R32, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false) }, - { GalImageFormat.A4B4G4R4, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false) }, - { GalImageFormat.BC6H_SF16, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false) }, - { GalImageFormat.BC6H_UF16, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false) }, - { GalImageFormat.A1R5G5B5, new ImageDescriptor(TextureReader.Read5551, true, false, false) }, - { GalImageFormat.B5G6R5, new ImageDescriptor(TextureReader.Read565, true, false, false) }, - { GalImageFormat.BC7, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false) }, - { GalImageFormat.R16G16, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false) }, - { GalImageFormat.R8G8, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false) }, - { GalImageFormat.G8R8, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false) }, - { GalImageFormat.R16, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false) }, - { GalImageFormat.R8, new ImageDescriptor(TextureReader.Read1Bpp, true, false, false) }, - { GalImageFormat.B10G11R11, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false) }, - { GalImageFormat.BC1_RGBA, new ImageDescriptor(TextureReader.Read8Bpt4x4, true, false, false) }, - { GalImageFormat.BC2, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false) }, - { GalImageFormat.BC3, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false) }, - { GalImageFormat.BC4, new ImageDescriptor(TextureReader.Read8Bpt4x4, true, false, false) }, - { GalImageFormat.BC5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false) }, - { GalImageFormat.ASTC_4x4, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false) }, - { GalImageFormat.ASTC_5x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture5x5, true, false, false) }, - { GalImageFormat.ASTC_6x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture6x6, true, false, false) }, - { GalImageFormat.ASTC_8x8, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x8, true, false, false) }, - { GalImageFormat.ASTC_10x10, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x10, true, false, false) }, - { GalImageFormat.ASTC_12x12, new ImageDescriptor(TextureReader.Read16BptCompressedTexture12x12, true, false, false) }, - { GalImageFormat.ASTC_5x4, new ImageDescriptor(TextureReader.Read16BptCompressedTexture5x4, true, false, false) }, - { GalImageFormat.ASTC_6x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture6x5, true, false, false) }, - { GalImageFormat.ASTC_8x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x6, true, false, false) }, - { GalImageFormat.ASTC_10x8, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x8, true, false, false) }, - { GalImageFormat.ASTC_12x10, new ImageDescriptor(TextureReader.Read16BptCompressedTexture12x10, true, false, false) }, - { GalImageFormat.ASTC_8x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x5, true, false, false) }, - { GalImageFormat.ASTC_10x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x5, true, false, false) }, - { GalImageFormat.ASTC_10x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x6, true, false, false) }, + { GalImageFormat.R32G32B32A32, new ImageDescriptor(TextureReader.Read16Bpp, true, false, false, false) }, + { GalImageFormat.R16G16B16A16, new ImageDescriptor(TextureReader.Read8Bpp, true, false, false, false) }, + { GalImageFormat.R32G32, new ImageDescriptor(TextureReader.Read8Bpp, true, false, false, false) }, + { GalImageFormat.A8B8G8R8, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) }, + { GalImageFormat.A2B10G10R10, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) }, + { GalImageFormat.R32, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) }, + { GalImageFormat.A4B4G4R4, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false, false) }, + { GalImageFormat.BC6H_SF16, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) }, + { GalImageFormat.BC6H_UF16, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) }, + { GalImageFormat.A1R5G5B5, new ImageDescriptor(TextureReader.Read5551, true, false, false, false) }, + { GalImageFormat.B5G6R5, new ImageDescriptor(TextureReader.Read565, true, false, false, false) }, + { GalImageFormat.BC7, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) }, + { GalImageFormat.R16G16, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) }, + { GalImageFormat.R8G8, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false, false) }, + { GalImageFormat.G8R8, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false, false) }, + { GalImageFormat.R16, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false, false) }, + { GalImageFormat.R8, new ImageDescriptor(TextureReader.Read1Bpp, true, false, false, false) }, + { GalImageFormat.B10G11R11, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) }, + { GalImageFormat.A8B8G8R8_SRGB, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) }, + { GalImageFormat.BC1_RGBA, new ImageDescriptor(TextureReader.Read8Bpt4x4, true, false, false, true) }, + { GalImageFormat.BC2, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) }, + { GalImageFormat.BC3, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) }, + { GalImageFormat.BC4, new ImageDescriptor(TextureReader.Read8Bpt4x4, true, false, false, true) }, + { GalImageFormat.BC5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) }, + { GalImageFormat.ASTC_4x4, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) }, + { GalImageFormat.ASTC_5x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture5x5, true, false, false, true) }, + { GalImageFormat.ASTC_6x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture6x6, true, false, false, true) }, + { GalImageFormat.ASTC_8x8, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x8, true, false, false, true) }, + { GalImageFormat.ASTC_10x10, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x10, true, false, false, true) }, + { GalImageFormat.ASTC_12x12, new ImageDescriptor(TextureReader.Read16BptCompressedTexture12x12, true, false, false, true) }, + { GalImageFormat.ASTC_5x4, new ImageDescriptor(TextureReader.Read16BptCompressedTexture5x4, true, false, false, true) }, + { GalImageFormat.ASTC_6x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture6x5, true, false, false, true) }, + { GalImageFormat.ASTC_8x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x6, true, false, false, true) }, + { GalImageFormat.ASTC_10x8, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x8, true, false, false, true) }, + { GalImageFormat.ASTC_12x10, new ImageDescriptor(TextureReader.Read16BptCompressedTexture12x10, true, false, false, true) }, + { GalImageFormat.ASTC_8x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x5, true, false, false, true) }, + { GalImageFormat.ASTC_10x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x5, true, false, false, true) }, + { GalImageFormat.ASTC_10x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x6, true, false, false, true) }, - { GalImageFormat.D24_S8, new ImageDescriptor(TextureReader.Read4Bpp, false, true, true) }, - { GalImageFormat.D32, new ImageDescriptor(TextureReader.Read4Bpp, false, true, false) }, - { GalImageFormat.D16, new ImageDescriptor(TextureReader.Read2Bpp, false, true, false) }, - { GalImageFormat.D32_S8, new ImageDescriptor(TextureReader.Read8Bpp, false, true, true) }, + { GalImageFormat.D24_S8, new ImageDescriptor(TextureReader.Read4Bpp, false, true, true, false) }, + { GalImageFormat.D32, new ImageDescriptor(TextureReader.Read4Bpp, false, true, false, false) }, + { GalImageFormat.D16, new ImageDescriptor(TextureReader.Read2Bpp, false, true, false, false) }, + { GalImageFormat.D32_S8, new ImageDescriptor(TextureReader.Read8Bpp, false, true, true, false) }, }; public static GalImageFormat ConvertTexture( @@ -204,7 +209,7 @@ namespace Ryujinx.Graphics.Texture return GetImageDescriptor(Format).Reader; } - public static int GetImageSize(GalImage Image) + public static int GetSize(GalImage Image) { switch (Image.Format & GalImageFormat.FormatMask) { @@ -310,6 +315,11 @@ namespace Ryujinx.Graphics.Texture return GetImageDescriptor(Format).HasStencil; } + public static bool IsCompressed(GalImageFormat Format) + { + return GetImageDescriptor(Format).Compressed; + } + private static ImageDescriptor GetImageDescriptor(GalImageFormat Format) { GalImageFormat TypeLess = (Format & GalImageFormat.FormatMask); @@ -319,7 +329,7 @@ namespace Ryujinx.Graphics.Texture return Descriptor; } - throw new NotImplementedException("Image with format " + TypeLess.ToString() + "not implemented"); + throw new NotImplementedException("Image with format " + TypeLess.ToString() + " not implemented"); } private static GalImageFormat GetFormatType(GalTextureType Type)