diff options
author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2018-09-08 14:51:50 -0300 |
---|---|---|
committer | gdkchan <gab.dark.100@gmail.com> | 2018-09-08 14:51:50 -0300 |
commit | ce1d5be212e6f71a7ca32c3bd7b48e32d9f51b9a (patch) | |
tree | 759fe422127ce08c545d4616ccc9691f668032ec /Ryujinx.Graphics/Texture/ImageUtils.cs | |
parent | a0c78f792012cdea060444d7cb6a36dbabb04d52 (diff) |
Move GPU emulation from Ryujinx.HLE to Ryujinx.Graphics and misc changes (#402)
* Move GPU LLE emulation from HLE to Graphics
* Graphics: Move Gal/Texture to Texture
* Remove Engines/ directory and namespace
* Use tables for image formats
* Abstract OpCode decoding
* Simplify image table
* Do not leak Read* symbols in TextureReader
* Fixups
* Rename IGalFrameBuffer -> IGalRenderTarget
* Remove MaxBpp hardcoded value
* Change yet again texture data and add G8R8 flipping
* Rename GalFrameBufferFormat to GalSurfaceFormat
* Unident EnsureSetup in ImageHandler
* Add IsCompressed
* Address some feedback
Diffstat (limited to 'Ryujinx.Graphics/Texture/ImageUtils.cs')
-rw-r--r-- | Ryujinx.Graphics/Texture/ImageUtils.cs | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Texture/ImageUtils.cs b/Ryujinx.Graphics/Texture/ImageUtils.cs new file mode 100644 index 00000000..ccea43ec --- /dev/null +++ b/Ryujinx.Graphics/Texture/ImageUtils.cs @@ -0,0 +1,357 @@ +using Ryujinx.Graphics.Gal; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Graphics.Texture +{ + static class ImageUtils + { + struct ImageDescriptor + { + public TextureReaderDelegate Reader; + + public bool HasColor; + public bool HasDepth; + public bool HasStencil; + + public bool Compressed; + + public ImageDescriptor( + TextureReaderDelegate Reader, + bool HasColor, + bool HasDepth, + bool HasStencil, + bool Compressed) + { + this.Reader = Reader; + this.HasColor = HasColor; + this.HasDepth = HasDepth; + this.HasStencil = HasStencil; + this.Compressed = Compressed; + } + } + + private const GalImageFormat Snorm = GalImageFormat.Snorm; + private const GalImageFormat Unorm = GalImageFormat.Unorm; + private const GalImageFormat Sint = GalImageFormat.Sint; + private const GalImageFormat Uint = GalImageFormat.Uint; + private const GalImageFormat Sfloat = GalImageFormat.Sfloat; + + private static readonly Dictionary<GalTextureFormat, GalImageFormat> s_TextureTable = + new Dictionary<GalTextureFormat, GalImageFormat>() + { + { GalTextureFormat.R32G32B32A32, GalImageFormat.R32G32B32A32 | Sint | Uint | Sfloat }, + { GalTextureFormat.R16G16B16A16, GalImageFormat.R16G16B16A16 | Snorm | Unorm | Sint | Uint | Sfloat }, + { GalTextureFormat.R32G32, GalImageFormat.R32G32 | Sint | Uint | Sfloat }, + { GalTextureFormat.A8B8G8R8, GalImageFormat.A8B8G8R8 | Snorm | Unorm | Sint | Uint }, + { GalTextureFormat.A2B10G10R10, GalImageFormat.A2B10G10R10 | Snorm | Unorm | Sint | Uint }, + { GalTextureFormat.G8R8, GalImageFormat.G8R8 | Snorm | Unorm | Sint | Uint }, + { GalTextureFormat.R16, GalImageFormat.R16 | Snorm | Unorm | Sint | Uint | Sfloat }, + { GalTextureFormat.R8, GalImageFormat.R8 | Snorm | Unorm | Sint | Uint }, + { GalTextureFormat.R32, GalImageFormat.R32 | Sint | Uint | Sfloat }, + { GalTextureFormat.A4B4G4R4, GalImageFormat.A4B4G4R4 | Unorm }, + { GalTextureFormat.A1B5G5R5, GalImageFormat.A1R5G5B5 | Unorm }, + { GalTextureFormat.B5G6R5, GalImageFormat.B5G6R5 | Unorm }, + { GalTextureFormat.BF10GF11RF11, GalImageFormat.B10G11R11 | Sfloat }, + { GalTextureFormat.Z24S8, GalImageFormat.D24_S8 | Unorm }, + { GalTextureFormat.ZF32, GalImageFormat.D32 | Sfloat }, + { GalTextureFormat.ZF32_X24S8, GalImageFormat.D32_S8 | Unorm }, + + //Compressed formats + { GalTextureFormat.BC6H_SF16, GalImageFormat.BC6H_SF16 | Unorm }, + { GalTextureFormat.BC6H_UF16, GalImageFormat.BC6H_UF16 | Unorm }, + { GalTextureFormat.BC7U, GalImageFormat.BC7 | Unorm }, + { GalTextureFormat.BC1, GalImageFormat.BC1_RGBA | Unorm }, + { GalTextureFormat.BC2, GalImageFormat.BC2 | Unorm }, + { GalTextureFormat.BC3, GalImageFormat.BC3 | Unorm }, + { GalTextureFormat.BC4, GalImageFormat.BC4 | Unorm | Snorm }, + { GalTextureFormat.BC5, GalImageFormat.BC5 | Unorm | Snorm }, + { GalTextureFormat.Astc2D4x4, GalImageFormat.ASTC_4x4 | Unorm }, + { GalTextureFormat.Astc2D5x5, GalImageFormat.ASTC_5x5 | Unorm }, + { GalTextureFormat.Astc2D6x6, GalImageFormat.ASTC_6x6 | Unorm }, + { GalTextureFormat.Astc2D8x8, GalImageFormat.ASTC_8x8 | Unorm }, + { GalTextureFormat.Astc2D10x10, GalImageFormat.ASTC_10x10 | Unorm }, + { GalTextureFormat.Astc2D12x12, GalImageFormat.ASTC_12x12 | Unorm }, + { GalTextureFormat.Astc2D5x4, GalImageFormat.ASTC_5x4 | Unorm }, + { GalTextureFormat.Astc2D6x5, GalImageFormat.ASTC_6x5 | Unorm }, + { GalTextureFormat.Astc2D8x6, GalImageFormat.ASTC_8x6 | Unorm }, + { GalTextureFormat.Astc2D10x8, GalImageFormat.ASTC_10x8 | Unorm }, + { GalTextureFormat.Astc2D12x10, GalImageFormat.ASTC_12x10 | Unorm }, + { GalTextureFormat.Astc2D8x5, GalImageFormat.ASTC_8x5 | Unorm }, + { GalTextureFormat.Astc2D10x5, GalImageFormat.ASTC_10x5 | Unorm }, + { GalTextureFormat.Astc2D10x6, GalImageFormat.ASTC_10x6 | Unorm } + }; + + private static readonly Dictionary<GalImageFormat, ImageDescriptor> s_ImageTable = + new Dictionary<GalImageFormat, ImageDescriptor>() + { + { 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, 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( + GalTextureFormat Format, + GalTextureType RType, + GalTextureType GType, + GalTextureType BType, + GalTextureType AType) + { + if (RType != GType || RType != BType || RType != AType) + { + throw new NotImplementedException("Per component types are not implemented"); + } + + if (!s_TextureTable.TryGetValue(Format, out GalImageFormat ImageFormat)) + { + throw new NotImplementedException("Texture with format " + ((int)Format).ToString("x2") + " not implemented"); + } + + GalTextureType Type = RType; + + GalImageFormat FormatType = GetFormatType(RType); + + if (ImageFormat.HasFlag(FormatType)) + { + return (ImageFormat & GalImageFormat.FormatMask) | FormatType; + } + else + { + throw new NotImplementedException("Texture with format " + Format + + " and component type " + Type + " is not implemented"); + } + } + + public static GalImageFormat ConvertSurface(GalSurfaceFormat Format) + { + switch (Format) + { + case GalSurfaceFormat.RGBA32Float: return GalImageFormat.R32G32B32A32 | Sfloat; + case GalSurfaceFormat.RGBA16Float: return GalImageFormat.R16G16B16A16 | Sfloat; + case GalSurfaceFormat.RG32Float: return GalImageFormat.R32G32 | Sfloat; + case GalSurfaceFormat.RG32Sint: return GalImageFormat.R32G32 | Sint; + case GalSurfaceFormat.RG32Uint: return GalImageFormat.R32G32 | Uint; + case GalSurfaceFormat.BGRA8Unorm: return GalImageFormat.R8G8B8A8 | Unorm; //Is this right? + case GalSurfaceFormat.BGRA8Srgb: return GalImageFormat.A8B8G8R8_SRGB; //This one might be wrong + case GalSurfaceFormat.RGB10A2Unorm: return GalImageFormat.A2B10G10R10 | Unorm; + case GalSurfaceFormat.RGBA8Unorm: return GalImageFormat.A8B8G8R8 | Unorm; + case GalSurfaceFormat.RGBA8Srgb: return GalImageFormat.A8B8G8R8_SRGB; + case GalSurfaceFormat.RGBA8Snorm: return GalImageFormat.A8B8G8R8 | Snorm; + case GalSurfaceFormat.RG16Snorm: return GalImageFormat.R16G16 | Snorm; + case GalSurfaceFormat.RG16Float: return GalImageFormat.R16G16 | Sfloat; + case GalSurfaceFormat.R11G11B10Float: return GalImageFormat.B10G11R11 | Sfloat; + case GalSurfaceFormat.R32Float: return GalImageFormat.R32 | Sfloat; + case GalSurfaceFormat.RG8Unorm: return GalImageFormat.R8G8 | Unorm; + case GalSurfaceFormat.RG8Snorm: return GalImageFormat.R8 | Snorm; + case GalSurfaceFormat.R16Float: return GalImageFormat.R16 | Sfloat; + case GalSurfaceFormat.R8Unorm: return GalImageFormat.R8 | Unorm; + } + + throw new NotImplementedException(Format.ToString()); + } + + public static GalImageFormat ConvertZeta(GalZetaFormat Format) + { + switch (Format) + { + case GalZetaFormat.Z32Float: return GalImageFormat.D32 | Sfloat; + case GalZetaFormat.S8Z24Unorm: return GalImageFormat.D24_S8 | Unorm; + case GalZetaFormat.Z16Unorm: return GalImageFormat.D16 | Unorm; + //This one might not be Uint, change when a texture uses this format + case GalZetaFormat.Z32S8X24Float: return GalImageFormat.D32_S8 | Uint; + } + + throw new NotImplementedException(Format.ToString()); + } + + public static TextureReaderDelegate GetReader(GalImageFormat Format) + { + return GetImageDescriptor(Format).Reader; + } + + public static int GetSize(GalImage Image) + { + switch (Image.Format & GalImageFormat.FormatMask) + { + case GalImageFormat.R32G32B32A32: + return Image.Width * Image.Height * 16; + + case GalImageFormat.R16G16B16A16: + case GalImageFormat.D32_S8: + case GalImageFormat.R32G32: + return Image.Width * Image.Height * 8; + + case GalImageFormat.A8B8G8R8: + case GalImageFormat.A8B8G8R8_SRGB: + case GalImageFormat.A2B10G10R10: + case GalImageFormat.R16G16: + case GalImageFormat.R32: + case GalImageFormat.D32: + case GalImageFormat.B10G11R11: + case GalImageFormat.D24_S8: + return Image.Width * Image.Height * 4; + + case GalImageFormat.B4G4R4A4: + case GalImageFormat.A1R5G5B5: + case GalImageFormat.B5G6R5: + case GalImageFormat.R8G8: + case GalImageFormat.R16: + case GalImageFormat.D16: + return Image.Width * Image.Height * 2; + + case GalImageFormat.R8: + return Image.Width * Image.Height; + + case GalImageFormat.BC1_RGBA: + case GalImageFormat.BC4: + { + return CompressedTextureSize(Image.Width, Image.Height, 4, 4, 8); + } + + case GalImageFormat.BC6H_SF16: + case GalImageFormat.BC6H_UF16: + case GalImageFormat.BC7: + case GalImageFormat.BC2: + case GalImageFormat.BC3: + case GalImageFormat.BC5: + case GalImageFormat.ASTC_4x4: + return CompressedTextureSize(Image.Width, Image.Height, 4, 4, 16); + + case GalImageFormat.ASTC_5x5: + return CompressedTextureSize(Image.Width, Image.Height, 5, 5, 16); + + case GalImageFormat.ASTC_6x6: + return CompressedTextureSize(Image.Width, Image.Height, 6, 6, 16); + + case GalImageFormat.ASTC_8x8: + return CompressedTextureSize(Image.Width, Image.Height, 8, 8, 16); + + case GalImageFormat.ASTC_10x10: + return CompressedTextureSize(Image.Width, Image.Height, 10, 10, 16); + + case GalImageFormat.ASTC_12x12: + return CompressedTextureSize(Image.Width, Image.Height, 12, 12, 16); + + case GalImageFormat.ASTC_5x4: + return CompressedTextureSize(Image.Width, Image.Height, 5, 4, 16); + + case GalImageFormat.ASTC_6x5: + return CompressedTextureSize(Image.Width, Image.Height, 6, 5, 16); + + case GalImageFormat.ASTC_8x6: + return CompressedTextureSize(Image.Width, Image.Height, 8, 6, 16); + + case GalImageFormat.ASTC_10x8: + return CompressedTextureSize(Image.Width, Image.Height, 10, 8, 16); + + case GalImageFormat.ASTC_12x10: + return CompressedTextureSize(Image.Width, Image.Height, 12, 10, 16); + + case GalImageFormat.ASTC_8x5: + return CompressedTextureSize(Image.Width, Image.Height, 8, 5, 16); + + case GalImageFormat.ASTC_10x5: + return CompressedTextureSize(Image.Width, Image.Height, 10, 5, 16); + + case GalImageFormat.ASTC_10x6: + return CompressedTextureSize(Image.Width, Image.Height, 10, 6, 16); + } + + throw new NotImplementedException((Image.Format & GalImageFormat.FormatMask).ToString()); + } + + public static bool HasColor(GalImageFormat Format) + { + return GetImageDescriptor(Format).HasColor; + } + + public static bool HasDepth(GalImageFormat Format) + { + return GetImageDescriptor(Format).HasDepth; + } + + public static bool HasStencil(GalImageFormat Format) + { + 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); + + if (s_ImageTable.TryGetValue(TypeLess, out ImageDescriptor Descriptor)) + { + return Descriptor; + } + + throw new NotImplementedException("Image with format " + TypeLess.ToString() + " not implemented"); + } + + private static GalImageFormat GetFormatType(GalTextureType Type) + { + switch (Type) + { + case GalTextureType.Snorm: return Snorm; + case GalTextureType.Unorm: return Unorm; + case GalTextureType.Sint: return Sint; + case GalTextureType.Uint: return Uint; + case GalTextureType.Float: return Sfloat; + + default: throw new NotImplementedException(((int)Type).ToString()); + } + } + + private static int CompressedTextureSize(int TextureWidth, int TextureHeight, int BlockWidth, int BlockHeight, int Bpb) + { + int W = (TextureWidth + (BlockWidth - 1)) / BlockWidth; + int H = (TextureHeight + (BlockHeight - 1)) / BlockHeight; + + return W * H * Bpb; + } + } +}
\ No newline at end of file |