aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Texture/ImageUtils.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics/Texture/ImageUtils.cs')
-rw-r--r--Ryujinx.Graphics/Texture/ImageUtils.cs364
1 files changed, 195 insertions, 169 deletions
diff --git a/Ryujinx.Graphics/Texture/ImageUtils.cs b/Ryujinx.Graphics/Texture/ImageUtils.cs
index f6db0894..7d3dde49 100644
--- a/Ryujinx.Graphics/Texture/ImageUtils.cs
+++ b/Ryujinx.Graphics/Texture/ImageUtils.cs
@@ -1,33 +1,37 @@
-using Ryujinx.Graphics.Gal;
+using ChocolArm64.Memory;
+using Ryujinx.Graphics.Gal;
+using Ryujinx.Graphics.Memory;
using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Texture
{
- static class ImageUtils
+ public static class ImageUtils
{
- struct ImageDescriptor
+ [Flags]
+ private enum TargetBuffer
{
- public TextureReaderDelegate Reader;
+ Color = 1 << 0,
+ Depth = 1 << 1,
+ Stencil = 1 << 2,
- public bool HasColor;
- public bool HasDepth;
- public bool HasStencil;
+ DepthStencil = Depth | Stencil
+ }
+
+ private struct ImageDescriptor
+ {
+ public int BytesPerPixel { get; private set; }
+ public int BlockWidth { get; private set; }
+ public int BlockHeight { get; private set; }
- public bool Compressed;
+ public TargetBuffer Target { get; private set; }
- public ImageDescriptor(
- TextureReaderDelegate Reader,
- bool HasColor,
- bool HasDepth,
- bool HasStencil,
- bool Compressed)
+ public ImageDescriptor(int BytesPerPixel, int BlockWidth, int BlockHeight, TargetBuffer Target)
{
- this.Reader = Reader;
- this.HasColor = HasColor;
- this.HasDepth = HasDepth;
- this.HasStencil = HasStencil;
- this.Compressed = Compressed;
+ this.BytesPerPixel = BytesPerPixel;
+ this.BlockWidth = BlockWidth;
+ this.BlockHeight = BlockHeight;
+ this.Target = Target;
}
}
@@ -48,6 +52,7 @@ namespace Ryujinx.Graphics.Texture
{ 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.R16G16, GalImageFormat.R16G16 | Snorm },
{ GalTextureFormat.R32, GalImageFormat.R32 | Sint | Uint | Sfloat },
{ GalTextureFormat.A4B4G4R4, GalImageFormat.A4B4G4R4 | Unorm },
{ GalTextureFormat.A1B5G5R5, GalImageFormat.A1R5G5B5 | Unorm },
@@ -85,58 +90,58 @@ namespace Ryujinx.Graphics.Texture
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) },
- };
+ {
+ { GalImageFormat.R32G32B32A32, new ImageDescriptor(16, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R16G16B16A16, new ImageDescriptor(8, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R32G32, new ImageDescriptor(8, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.A8B8G8R8, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.A2B10G10R10, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R32, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.A4B4G4R4, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.BC6H_SF16, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC6H_UF16, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.A1R5G5B5, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.B5G6R5, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.BC7, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.R16G16, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R8G8, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.G8R8, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R16, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R8, new ImageDescriptor(1, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.B10G11R11, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.A8B8G8R8_SRGB, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.BC1_RGBA, new ImageDescriptor(8, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC2, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC3, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC4, new ImageDescriptor(8, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC5, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_4x4, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_5x5, new ImageDescriptor(16, 5, 5, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_6x6, new ImageDescriptor(16, 6, 6, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_8x8, new ImageDescriptor(16, 8, 8, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_10x10, new ImageDescriptor(16, 10, 10, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_12x12, new ImageDescriptor(16, 12, 12, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_5x4, new ImageDescriptor(16, 5, 4, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_6x5, new ImageDescriptor(16, 6, 5, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_8x6, new ImageDescriptor(16, 8, 6, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_10x8, new ImageDescriptor(16, 10, 8, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_12x10, new ImageDescriptor(16, 12, 10, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_8x5, new ImageDescriptor(16, 8, 5, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_10x5, new ImageDescriptor(16, 10, 5, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_10x6, new ImageDescriptor(16, 10, 6, TargetBuffer.Color) },
+
+ { GalImageFormat.D24_S8, new ImageDescriptor(4, 1, 1, TargetBuffer.DepthStencil) },
+ { GalImageFormat.D32, new ImageDescriptor(4, 1, 1, TargetBuffer.Depth) },
+ { GalImageFormat.D16, new ImageDescriptor(2, 1, 1, TargetBuffer.Depth) },
+ { GalImageFormat.D32_S8, new ImageDescriptor(8, 1, 1, TargetBuffer.DepthStencil) },
+ };
public static GalImageFormat ConvertTexture(
GalTextureFormat Format,
- GalTextureType RType,
- GalTextureType GType,
- GalTextureType BType,
- GalTextureType AType)
+ GalTextureType RType,
+ GalTextureType GType,
+ GalTextureType BType,
+ GalTextureType AType)
{
if (RType != GType || RType != BType || RType != AType)
{
@@ -202,128 +207,157 @@ namespace Ryujinx.Graphics.Texture
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;
+ case GalZetaFormat.Z24S8Unorm: return GalImageFormat.D24_S8 | Unorm;
+ case GalZetaFormat.Z32S8X24Float: return GalImageFormat.D32_S8 | Sfloat;
}
throw new NotImplementedException(Format.ToString());
}
- public static TextureReaderDelegate GetReader(GalImageFormat Format)
+ public static byte[] ReadTexture(IAMemory Memory, GalImage Image, long Position)
+ {
+ AMemory CpuMemory;
+
+ if (Memory is NvGpuVmm Vmm)
+ {
+ CpuMemory = Vmm.Memory;
+ }
+ else
+ {
+ CpuMemory = (AMemory)Memory;
+ }
+
+ ISwizzle Swizzle = TextureHelper.GetSwizzle(Image);
+
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ (int Width, int Height) = GetImageSizeInBlocks(Image);
+
+ int BytesPerPixel = Desc.BytesPerPixel;
+
+ int OutOffs = 0;
+
+ byte[] Data = new byte[Width * Height * BytesPerPixel];
+
+ for (int Y = 0; Y < Height; Y++)
+ for (int X = 0; X < Width; X++)
+ {
+ long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
+
+ CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel);
+
+ OutOffs += BytesPerPixel;
+ }
+
+ return Data;
+ }
+
+ public static void WriteTexture(NvGpuVmm Vmm, GalImage Image, long Position, byte[] Data)
{
- return GetImageDescriptor(Format).Reader;
+ ISwizzle Swizzle = TextureHelper.GetSwizzle(Image);
+
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ (int Width, int Height) = ImageUtils.GetImageSizeInBlocks(Image);
+
+ int BytesPerPixel = Desc.BytesPerPixel;
+
+ int InOffs = 0;
+
+ for (int Y = 0; Y < Height; Y++)
+ for (int X = 0; X < Width; X++)
+ {
+ long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
+
+ Vmm.Memory.WriteBytes(Position + Offset, Data, InOffs, BytesPerPixel);
+
+ InOffs += BytesPerPixel;
+ }
}
public static int GetSize(GalImage Image)
{
- switch (Image.Format & GalImageFormat.FormatMask)
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ int Width = DivRoundUp(Image.Width, Desc.BlockWidth);
+ int Height = DivRoundUp(Image.Height, Desc.BlockHeight);
+
+ return Desc.BytesPerPixel * Width * Height;
+ }
+
+ public static int GetPitch(GalImageFormat Format, int Width)
+ {
+ ImageDescriptor Desc = GetImageDescriptor(Format);
+
+ return Desc.BytesPerPixel * DivRoundUp(Width, Desc.BlockWidth);
+ }
+
+ public static int GetBlockWidth(GalImageFormat Format)
+ {
+ return GetImageDescriptor(Format).BlockWidth;
+ }
+
+ public static int GetBlockHeight(GalImageFormat Format)
+ {
+ return GetImageDescriptor(Format).BlockHeight;
+ }
+
+ public static int GetAlignedWidth(GalImage Image)
+ {
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ int AlignMask;
+
+ if (Image.Layout == GalMemoryLayout.BlockLinear)
{
- 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.G8R8:
- 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);
+ AlignMask = Image.TileWidth * (64 / Desc.BytesPerPixel) - 1;
+ }
+ else
+ {
+ AlignMask = (32 / Desc.BytesPerPixel) - 1;
}
- throw new NotImplementedException((Image.Format & GalImageFormat.FormatMask).ToString());
+ return (Image.Width + AlignMask) & ~AlignMask;
+ }
+
+ public static (int Width, int Height) GetImageSizeInBlocks(GalImage Image)
+ {
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ return (DivRoundUp(Image.Width, Desc.BlockWidth),
+ DivRoundUp(Image.Height, Desc.BlockHeight));
+ }
+
+ public static int GetBytesPerPixel(GalImageFormat Format)
+ {
+ return GetImageDescriptor(Format).BytesPerPixel;
+ }
+
+ private static int DivRoundUp(int LHS, int RHS)
+ {
+ return (LHS + (RHS - 1)) / RHS;
}
public static bool HasColor(GalImageFormat Format)
{
- return GetImageDescriptor(Format).HasColor;
+ return (GetImageDescriptor(Format).Target & TargetBuffer.Color) != 0;
}
public static bool HasDepth(GalImageFormat Format)
{
- return GetImageDescriptor(Format).HasDepth;
+ return (GetImageDescriptor(Format).Target & TargetBuffer.Depth) != 0;
}
public static bool HasStencil(GalImageFormat Format)
{
- return GetImageDescriptor(Format).HasStencil;
+ return (GetImageDescriptor(Format).Target & TargetBuffer.Stencil) != 0;
}
public static bool IsCompressed(GalImageFormat Format)
{
- return GetImageDescriptor(Format).Compressed;
+ ImageDescriptor Desc = GetImageDescriptor(Format);
+
+ return (Desc.BlockWidth | Desc.BlockHeight) != 1;
}
private static ImageDescriptor GetImageDescriptor(GalImageFormat Format)
@@ -351,13 +385,5 @@ namespace Ryujinx.Graphics.Texture
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