Allow "reinterpretation" of framebuffer/zeta formats (#418)

* (Re)Implement format reinterpretation, other changes

* Implement writeback to guest memory, some refactoring

* More refactoring, implement reinterpretation the old way again

* Clean up

* Some fixes on M2MF (old Dma engine), added partial support for P2MF, fix conditional ssy, add Z24S8 zeta format, other fixes

* nit: Formatting

* Address PR feedback
This commit is contained in:
gdkchan
2018-09-18 01:30:35 -03:00
committed by GitHub
parent bec95cacc1
commit d4187aaa9d
52 changed files with 1594 additions and 1979 deletions

View File

@ -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
}
public bool Compressed;
private struct ImageDescriptor
{
public int BytesPerPixel { get; private set; }
public int BlockWidth { get; private set; }
public int BlockHeight { get; private set; }
public ImageDescriptor(
TextureReaderDelegate Reader,
bool HasColor,
bool HasDepth,
bool HasStencil,
bool Compressed)
public TargetBuffer Target { get; private set; }
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.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(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.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)
{
return GetImageDescriptor(Format).Reader;
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)
{
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;
}
}
}

View File

@ -17,44 +17,20 @@ namespace Ryujinx.Graphics.Texture
GalTextureSource ZSource = (GalTextureSource)((Tic[0] >> 25) & 7);
GalTextureSource WSource = (GalTextureSource)((Tic[0] >> 28) & 7);
int Width = (Tic[4] & 0xffff) + 1;
int Height = (Tic[5] & 0xffff) + 1;
return new GalImage(
Width,
Height,
Format,
XSource,
YSource,
ZSource,
WSource);
}
public static byte[] GetTextureData(NvGpuVmm Vmm, long TicPosition)
{
int[] Tic = ReadWords(Vmm, TicPosition, 8);
GalImageFormat Format = GetImageFormat(Tic);
long TextureAddress = (uint)Tic[1];
TextureAddress |= (long)((ushort)Tic[2]) << 32;
TextureSwizzle Swizzle = (TextureSwizzle)((Tic[2] >> 21) & 7);
GalMemoryLayout Layout;
if (Swizzle == TextureSwizzle.BlockLinear ||
Swizzle == TextureSwizzle.BlockLinearColorKey)
{
TextureAddress &= ~0x1ffL;
Layout = GalMemoryLayout.BlockLinear;
}
else if (Swizzle == TextureSwizzle.Pitch ||
Swizzle == TextureSwizzle.PitchColorKey)
else
{
TextureAddress &= ~0x1fL;
Layout = GalMemoryLayout.Pitch;
}
int Pitch = (Tic[3] & 0xffff) << 5;
int BlockHeightLog2 = (Tic[3] >> 3) & 7;
int TileWidthLog2 = (Tic[3] >> 10) & 7;
@ -64,17 +40,17 @@ namespace Ryujinx.Graphics.Texture
int Width = (Tic[4] & 0xffff) + 1;
int Height = (Tic[5] & 0xffff) + 1;
TextureInfo Texture = new TextureInfo(
TextureAddress,
return new GalImage(
Width,
Height,
Pitch,
BlockHeight,
TileWidth,
Swizzle,
Format);
return TextureReader.Read(Vmm, Texture);
BlockHeight,
Layout,
Format,
XSource,
YSource,
ZSource,
WSource);
}
public static GalTextureSampler MakeSampler(NvGpu Gpu, NvGpuVmm Vmm, long TscPosition)
@ -107,7 +83,7 @@ namespace Ryujinx.Graphics.Texture
private static GalImageFormat GetImageFormat(int[] Tic)
{
GalTextureType RType = (GalTextureType)((Tic[0] >> 7) & 7);
GalTextureType RType = (GalTextureType)((Tic[0] >> 7) & 7);
GalTextureType GType = (GalTextureType)((Tic[0] >> 10) & 7);
GalTextureType BType = (GalTextureType)((Tic[0] >> 13) & 7);
GalTextureType AType = (GalTextureType)((Tic[0] >> 16) & 7);

View File

@ -1,33 +1,30 @@
using ChocolArm64.Memory;
using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory;
using System;
namespace Ryujinx.Graphics.Texture
{
static class TextureHelper
{
public static ISwizzle GetSwizzle(TextureInfo Texture, int BlockWidth, int Bpp)
public static ISwizzle GetSwizzle(GalImage Image)
{
int Width = (Texture.Width + (BlockWidth - 1)) / BlockWidth;
int BlockWidth = ImageUtils.GetBlockWidth (Image.Format);
int BytesPerPixel = ImageUtils.GetBytesPerPixel(Image.Format);
int AlignMask = Texture.TileWidth * (64 / Bpp) - 1;
int Width = (Image.Width + (BlockWidth - 1)) / BlockWidth;
Width = (Width + AlignMask) & ~AlignMask;
switch (Texture.Swizzle)
if (Image.Layout == GalMemoryLayout.BlockLinear)
{
case TextureSwizzle._1dBuffer:
case TextureSwizzle.Pitch:
case TextureSwizzle.PitchColorKey:
return new LinearSwizzle(Texture.Pitch, Bpp);
int AlignMask = Image.TileWidth * (64 / BytesPerPixel) - 1;
case TextureSwizzle.BlockLinear:
case TextureSwizzle.BlockLinearColorKey:
return new BlockLinearSwizzle(Width, Bpp, Texture.BlockHeight);
Width = (Width + AlignMask) & ~AlignMask;
return new BlockLinearSwizzle(Width, BytesPerPixel, Image.GobBlockHeight);
}
else
{
return new LinearSwizzle(Image.Pitch, BytesPerPixel);
}
throw new NotImplementedException(Texture.Swizzle.ToString());
}
public static (AMemory Memory, long Position) GetMemoryAndPosition(

View File

@ -1,60 +0,0 @@
using Ryujinx.Graphics.Gal;
namespace Ryujinx.Graphics.Texture
{
public struct TextureInfo
{
public long Position { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }
public int Pitch { get; private set; }
public int BlockHeight { get; private set; }
public int TileWidth { get; private set; }
public TextureSwizzle Swizzle { get; private set; }
public GalImageFormat Format { get; private set; }
public TextureInfo(
long Position,
int Width,
int Height)
{
this.Position = Position;
this.Width = Width;
this.Height = Height;
Pitch = 0;
BlockHeight = 16;
TileWidth = 1;
Swizzle = TextureSwizzle.BlockLinear;
Format = GalImageFormat.A8B8G8R8 | GalImageFormat.Unorm;
}
public TextureInfo(
long Position,
int Width,
int Height,
int Pitch,
int BlockHeight,
int TileWidth,
TextureSwizzle Swizzle,
GalImageFormat Format)
{
this.Position = Position;
this.Width = Width;
this.Height = Height;
this.Pitch = Pitch;
this.BlockHeight = BlockHeight;
this.TileWidth = TileWidth;
this.Swizzle = Swizzle;
this.Format = Format;
}
}
}

View File

@ -1,398 +0,0 @@
using ChocolArm64.Memory;
using Ryujinx.Graphics.Gal;
using System;
namespace Ryujinx.Graphics.Texture
{
delegate byte[] TextureReaderDelegate(IAMemory Memory, TextureInfo Texture);
public static class TextureReader
{
public static byte[] Read(IAMemory Memory, TextureInfo Texture)
{
TextureReaderDelegate Reader = ImageUtils.GetReader(Texture.Format);
return Reader(Memory, Texture);
}
internal unsafe static byte[] Read1Bpp(IAMemory Memory, TextureInfo Texture)
{
int Width = Texture.Width;
int Height = Texture.Height;
byte[] Output = new byte[Width * Height];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 1);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
byte Pixel = CpuMem.ReadByte(Position + Offset);
*(BuffPtr + OutOffs) = Pixel;
OutOffs++;
}
}
return Output;
}
internal unsafe static byte[] Read5551(IAMemory Memory, TextureInfo Texture)
{
int Width = Texture.Width;
int Height = Texture.Height;
byte[] Output = new byte[Width * Height * 2];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
uint Pixel = (uint)CpuMem.ReadInt16(Position + Offset);
Pixel = (Pixel & 0x001f) << 11 |
(Pixel & 0x03e0) << 1 |
(Pixel & 0x7c00) >> 9 |
(Pixel & 0x8000) >> 15;
*(short*)(BuffPtr + OutOffs) = (short)Pixel;
OutOffs += 2;
}
}
return Output;
}
internal unsafe static byte[] Read565(IAMemory Memory, TextureInfo Texture)
{
int Width = Texture.Width;
int Height = Texture.Height;
byte[] Output = new byte[Width * Height * 2];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
uint Pixel = (uint)CpuMem.ReadInt16(Position + Offset);
Pixel = (Pixel & 0x001f) << 11 |
(Pixel & 0x07e0) |
(Pixel & 0xf800) >> 11;
*(short*)(BuffPtr + OutOffs) = (short)Pixel;
OutOffs += 2;
}
}
return Output;
}
internal unsafe static byte[] Read2Bpp(IAMemory Memory, TextureInfo Texture)
{
int Width = Texture.Width;
int Height = Texture.Height;
byte[] Output = new byte[Width * Height * 2];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
short Pixel = CpuMem.ReadInt16(Position + Offset);
*(short*)(BuffPtr + OutOffs) = Pixel;
OutOffs += 2;
}
}
return Output;
}
internal unsafe static byte[] Read4Bpp(IAMemory Memory, TextureInfo Texture)
{
int Width = Texture.Width;
int Height = Texture.Height;
byte[] Output = new byte[Width * Height * 4];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
int Pixel = CpuMem.ReadInt32(Position + Offset);
*(int*)(BuffPtr + OutOffs) = Pixel;
OutOffs += 4;
}
}
return Output;
}
internal unsafe static byte[] Read8Bpp(IAMemory Memory, TextureInfo Texture)
{
int Width = Texture.Width;
int Height = Texture.Height;
byte[] Output = new byte[Width * Height * 8];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 8);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
long Pixel = CpuMem.ReadInt64(Position + Offset);
*(long*)(BuffPtr + OutOffs) = Pixel;
OutOffs += 8;
}
}
return Output;
}
internal unsafe static byte[] Read16Bpp(IAMemory Memory, TextureInfo Texture)
{
int Width = Texture.Width;
int Height = Texture.Height;
byte[] Output = new byte[Width * Height * 16];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 16);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
long PxLow = CpuMem.ReadInt64(Position + Offset + 0);
long PxHigh = CpuMem.ReadInt64(Position + Offset + 8);
*(long*)(BuffPtr + OutOffs + 0) = PxLow;
*(long*)(BuffPtr + OutOffs + 8) = PxHigh;
OutOffs += 16;
}
}
return Output;
}
internal unsafe static byte[] Read8Bpt4x4(IAMemory Memory, TextureInfo Texture)
{
int Width = (Texture.Width + 3) / 4;
int Height = (Texture.Height + 3) / 4;
byte[] Output = new byte[Width * Height * 8];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 4, 8);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
long Tile = CpuMem.ReadInt64(Position + Offset);
*(long*)(BuffPtr + OutOffs) = Tile;
OutOffs += 8;
}
}
return Output;
}
internal unsafe static byte[] Read16BptCompressedTexture(IAMemory Memory, TextureInfo Texture, int BlockWidth, int BlockHeight)
{
int Width = (Texture.Width + (BlockWidth - 1)) / BlockWidth;
int Height = (Texture.Height + (BlockHeight - 1)) / BlockHeight;
byte[] Output = new byte[Width * Height * 16];
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, BlockWidth, 16);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Output)
{
long OutOffs = 0;
for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
long Tile0 = CpuMem.ReadInt64(Position + Offset + 0);
long Tile1 = CpuMem.ReadInt64(Position + Offset + 8);
*(long*)(BuffPtr + OutOffs + 0) = Tile0;
*(long*)(BuffPtr + OutOffs + 8) = Tile1;
OutOffs += 16;
}
}
return Output;
}
internal static byte[] Read16BptCompressedTexture4x4(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 4, 4);
}
internal static byte[] Read16BptCompressedTexture5x5(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 5, 5);
}
internal static byte[] Read16BptCompressedTexture6x6(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 6, 6);
}
internal static byte[] Read16BptCompressedTexture8x8(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 8, 8);
}
internal static byte[] Read16BptCompressedTexture10x10(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 10, 10);
}
internal static byte[] Read16BptCompressedTexture12x12(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 12, 12);
}
internal static byte[] Read16BptCompressedTexture5x4(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 5, 4);
}
internal static byte[] Read16BptCompressedTexture6x5(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 6, 5);
}
internal static byte[] Read16BptCompressedTexture8x6(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 8, 6);
}
internal static byte[] Read16BptCompressedTexture10x8(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 10, 8);
}
internal static byte[] Read16BptCompressedTexture12x10(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 12, 10);
}
internal static byte[] Read16BptCompressedTexture8x5(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 5, 5);
}
internal static byte[] Read16BptCompressedTexture10x5(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 10, 5);
}
internal static byte[] Read16BptCompressedTexture10x6(IAMemory Memory, TextureInfo Texture)
{
return Read16BptCompressedTexture(Memory, Texture, 10, 6);
}
}
}

View File

@ -1,35 +0,0 @@
using ChocolArm64.Memory;
using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory;
namespace Ryujinx.Graphics.Texture
{
static class TextureWriter
{
public unsafe static void Write(IAMemory Memory, TextureInfo Texture, byte[] Data)
{
ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
(AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
Memory,
Texture.Position);
fixed (byte* BuffPtr = Data)
{
long InOffs = 0;
for (int Y = 0; Y < Texture.Height; Y++)
for (int X = 0; X < Texture.Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
int Pixel = *(int*)(BuffPtr + InOffs);
CpuMem.WriteInt32(Position + Offset, Pixel);
InOffs += 4;
}
}
}
}
}