Support depth in read/writeTexture

Also support WrapR and detect mipmap
This commit is contained in:
Thog 2018-11-22 09:36:20 +01:00
commit 5f0da0245e
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
13 changed files with 206 additions and 103 deletions

View file

@ -10,6 +10,7 @@ namespace Ryujinx.Graphics.Gal
public int TileWidth; public int TileWidth;
public int GobBlockHeight; public int GobBlockHeight;
public int Pitch; public int Pitch;
public int MaxMipmapLevel;
public GalImageFormat Format; public GalImageFormat Format;
public GalMemoryLayout Layout; public GalMemoryLayout Layout;
@ -28,10 +29,11 @@ namespace Ryujinx.Graphics.Gal
GalMemoryLayout Layout, GalMemoryLayout Layout,
GalImageFormat Format, GalImageFormat Format,
TextureType TextureType, TextureType TextureType,
GalTextureSource XSource = GalTextureSource.Red, int MaxMipmapLevel = 1,
GalTextureSource YSource = GalTextureSource.Green, GalTextureSource XSource = GalTextureSource.Red,
GalTextureSource ZSource = GalTextureSource.Blue, GalTextureSource YSource = GalTextureSource.Green,
GalTextureSource WSource = GalTextureSource.Alpha) GalTextureSource ZSource = GalTextureSource.Blue,
GalTextureSource WSource = GalTextureSource.Alpha)
{ {
this.Width = Width; this.Width = Width;
this.Height = Height; this.Height = Height;
@ -40,6 +42,7 @@ namespace Ryujinx.Graphics.Gal
this.GobBlockHeight = GobBlockHeight; this.GobBlockHeight = GobBlockHeight;
this.Layout = Layout; this.Layout = Layout;
this.Format = Format; this.Format = Format;
this.MaxMipmapLevel = MaxMipmapLevel;
this.XSource = XSource; this.XSource = XSource;
this.YSource = YSource; this.YSource = YSource;
this.ZSource = ZSource; this.ZSource = ZSource;

View file

@ -8,6 +8,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public int Width => Image.Width; public int Width => Image.Width;
public int Height => Image.Height; public int Height => Image.Height;
public int Depth => Image.Depth;
public GalImageFormat Format => Image.Format; public GalImageFormat Format => Image.Format;

View file

@ -2,6 +2,7 @@ using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
using System; using System;
using System.Diagnostics;
namespace Ryujinx.Graphics.Gal.OpenGL namespace Ryujinx.Graphics.Gal.OpenGL
{ {
@ -46,6 +47,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
const int Level = 0; //TODO: Support mipmap textures. const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0; const int Border = 0;
Debug.Assert(Image.MaxMipmapLevel != 1, "No Mipmap support");
TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size); TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size);
if (ImageUtils.IsCompressed(Image.Format)) if (ImageUtils.IsCompressed(Image.Format))
@ -87,7 +90,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
break; break;
default: default:
Logger.PrintWarning(LogClass.Gpu, $"Unsupported texture target type: {Target}"); Logger.PrintWarning(LogClass.Gpu, $"Unsupported texture target type: {Target}");
//throw new InvalidOperationException(); throw new InvalidOperationException();
GL.TexImage2D( GL.TexImage2D(
TextureTarget.Texture2D, TextureTarget.Texture2D,
Level, Level,
@ -115,6 +118,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
const int Level = 0; //TODO: Support mipmap textures. const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0; const int Border = 0;
Debug.Assert(Image.MaxMipmapLevel != 1, "No Mipmap support");
TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length); TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
if (ImageUtils.IsCompressed(Image.Format) && !IsAstc(Image.Format)) if (ImageUtils.IsCompressed(Image.Format) && !IsAstc(Image.Format))
@ -195,14 +200,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format); int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format);
int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format); int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format);
int TextureBlockDepth = ImageUtils.GetBlockDepth(Image.Format);
// TODO: support 3D textures
Data = ASTCDecoder.DecodeToRGBA8888( Data = ASTCDecoder.DecodeToRGBA8888(
Data, Data,
TextureBlockWidth, TextureBlockWidth,
TextureBlockHeight, 1, TextureBlockHeight,
TextureBlockDepth,
Image.Width, Image.Width,
Image.Height, 1); Image.Height,
Image.Depth);
Image.Format = GalImageFormat.RGBA8 | (Image.Format & GalImageFormat.TypeMask); Image.Format = GalImageFormat.RGBA8 | (Image.Format & GalImageFormat.TypeMask);
} }
@ -211,16 +218,50 @@ namespace Ryujinx.Graphics.Gal.OpenGL
PixelFormat Format, PixelFormat Format,
PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format); PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
GL.TexImage2D(
TextureTarget.Texture2D, switch (Target)
Level, {
InternalFmt, case TextureTarget.Texture2D:
Image.Width, GL.TexImage2D(
Image.Height, Target,
Border, Level,
Format, InternalFmt,
Type, Image.Width,
Data); Image.Height,
Border,
Format,
Type,
Data);
break;
case TextureTarget.Texture2DArray:
case TextureTarget.Texture3D:
GL.TexImage3D(
Target,
Level,
InternalFmt,
Image.Width,
Image.Height,
Image.Depth,
Border,
Format,
Type,
Data);
break;
default:
Logger.PrintWarning(LogClass.Gpu, $"Unsupported texture target type: {Target}");
throw new InvalidOperationException();
GL.TexImage2D(
TextureTarget.Texture2D,
Level,
InternalFmt,
Image.Width,
Image.Height,
Border,
Format,
Type,
Data);
break;
}
} }
} }
@ -283,6 +324,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU); int WrapS = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressU);
int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV); int WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
int WrapR = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressP);
int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter); int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter);
int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter); int MagFilter = (int)OGLEnumConverter.GetTextureMagFilter(Sampler.MagFilter);
@ -291,6 +333,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.TexParameter(Target, TextureParameterName.TextureWrapS, WrapS); GL.TexParameter(Target, TextureParameterName.TextureWrapS, WrapS);
GL.TexParameter(Target, TextureParameterName.TextureWrapT, WrapT); GL.TexParameter(Target, TextureParameterName.TextureWrapT, WrapT);
GL.TexParameter(Target, TextureParameterName.TextureWrapR, WrapR);
GL.TexParameter(Target, TextureParameterName.TextureMinFilter, MinFilter); GL.TexParameter(Target, TextureParameterName.TextureMinFilter, MinFilter);
GL.TexParameter(Target, TextureParameterName.TextureMagFilter, MagFilter); GL.TexParameter(Target, TextureParameterName.TextureMagFilter, MagFilter);

View file

@ -38,6 +38,7 @@ namespace Ryujinx.Graphics.Graphics3d
} }
} }
// FIXME: SUPPORT NON 2D
private void TextureCopy(NvGpuVmm Vmm) private void TextureCopy(NvGpuVmm Vmm)
{ {
CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation); CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation);
@ -82,8 +83,6 @@ namespace Ryujinx.Graphics.Graphics3d
long SrcKey = Vmm.GetPhysicalAddress(SrcAddress); long SrcKey = Vmm.GetPhysicalAddress(SrcAddress);
long DstKey = Vmm.GetPhysicalAddress(DstAddress); long DstKey = Vmm.GetPhysicalAddress(DstAddress);
// TODO: all texture types
GalImage SrcTexture = new GalImage( GalImage SrcTexture = new GalImage(
SrcWidth, SrcWidth,
SrcHeight, 1, 1, SrcHeight, 1, 1,

View file

@ -125,29 +125,29 @@ namespace Ryujinx.Graphics.Graphics3d
if (SrcLinear) if (SrcLinear)
{ {
SrcSwizzle = new LinearSwizzle(SrcPitch, SrcCpp); SrcSwizzle = new LinearSwizzle(SrcPitch, SrcCpp, SrcSizeX, SrcSizeY);
} }
else else
{ {
SrcSwizzle = new BlockLinearSwizzle(SrcSizeX, SrcCpp, SrcBlockHeight); SrcSwizzle = new BlockLinearSwizzle(SrcSizeX, SrcSizeY, SrcCpp, SrcBlockHeight);
} }
ISwizzle DstSwizzle; ISwizzle DstSwizzle;
if (DstLinear) if (DstLinear)
{ {
DstSwizzle = new LinearSwizzle(DstPitch, DstCpp); DstSwizzle = new LinearSwizzle(DstPitch, DstCpp, SrcSizeX, SrcSizeY);
} }
else else
{ {
DstSwizzle = new BlockLinearSwizzle(DstSizeX, DstCpp, DstBlockHeight); DstSwizzle = new BlockLinearSwizzle(DstSizeX, DstSizeY, DstCpp, DstBlockHeight);
} }
for (int Y = 0; Y < YCount; Y++) for (int Y = 0; Y < YCount; Y++)
for (int X = 0; X < XCount; X++) for (int X = 0; X < XCount; X++)
{ {
int SrcOffset = SrcSwizzle.GetSwizzleOffset(SrcPosX + X, SrcPosY + Y); int SrcOffset = SrcSwizzle.GetSwizzleOffset(SrcPosX + X, SrcPosY + Y, 0);
int DstOffset = DstSwizzle.GetSwizzleOffset(DstPosX + X, DstPosY + Y); int DstOffset = DstSwizzle.GetSwizzleOffset(DstPosX + X, DstPosY + Y, 0);
long Src = SrcPA + (uint)SrcOffset; long Src = SrcPA + (uint)SrcOffset;
long Dst = DstPA + (uint)DstOffset; long Dst = DstPA + (uint)DstOffset;

View file

@ -119,14 +119,14 @@ namespace Ryujinx.Graphics.Graphics3d
} }
else else
{ {
BlockLinearSwizzle Swizzle = new BlockLinearSwizzle(CopyWidth, 1, CopyGobBlockHeight); BlockLinearSwizzle Swizzle = new BlockLinearSwizzle(CopyWidth, CopyHeight, 1, CopyGobBlockHeight);
int SrcOffset = 0; int SrcOffset = 0;
for (int Y = CopyStartY; Y < CopyHeight && SrcOffset < CopySize; Y++) for (int Y = CopyStartY; Y < CopyHeight && SrcOffset < CopySize; Y++)
for (int X = CopyStartX; X < CopyWidth && SrcOffset < CopySize; X++) for (int X = CopyStartX; X < CopyWidth && SrcOffset < CopySize; X++)
{ {
int DstOffset = Swizzle.GetSwizzleOffset(X, Y); int DstOffset = Swizzle.GetSwizzleOffset(X, Y, 0);
Vmm.WriteByte(CopyAddress + DstOffset, Buffer[SrcOffset++]); Vmm.WriteByte(CopyAddress + DstOffset, Buffer[SrcOffset++]);
} }

View file

@ -72,6 +72,7 @@ namespace Ryujinx.Graphics.Texture
if (BlockZ != 1 || Z != 1) if (BlockZ != 1 || Z != 1)
{ {
// TODO: support 3D textures?
throw new ASTCDecoderException("3D compressed textures unsupported!"); throw new ASTCDecoderException("3D compressed textures unsupported!");
} }

View file

@ -11,7 +11,9 @@ namespace Ryujinx.Graphics.Texture
private int XShift; private int XShift;
private int GobStride; private int GobStride;
public BlockLinearSwizzle(int Width, int Bpp, int BlockHeight = 16) private int LayerZ;
public BlockLinearSwizzle(int Width, int Height, int Bpp, int BlockHeight)
{ {
BhMask = (BlockHeight * 8) - 1; BhMask = (BlockHeight * 8) - 1;
@ -23,6 +25,8 @@ namespace Ryujinx.Graphics.Texture
GobStride = 512 * BlockHeight * WidthInGobs; GobStride = 512 * BlockHeight * WidthInGobs;
XShift = CountLsbZeros(512 * BlockHeight); XShift = CountLsbZeros(512 * BlockHeight);
LayerZ = Bpp * Width * Height;
} }
private int CountLsbZeros(int Value) private int CountLsbZeros(int Value)
@ -37,7 +41,7 @@ namespace Ryujinx.Graphics.Texture
return Count; return Count;
} }
public int GetSwizzleOffset(int X, int Y) public int GetSwizzleOffset(int X, int Y, int Z)
{ {
X <<= BppShift; X <<= BppShift;
@ -53,7 +57,7 @@ namespace Ryujinx.Graphics.Texture
Position += ((Y & 0x01) >> 0) << 4; Position += ((Y & 0x01) >> 0) << 4;
Position += ((X & 0x0f) >> 0) << 0; Position += ((X & 0x0f) >> 0) << 0;
return Position; return (Z * LayerZ) + Position;
} }
} }
} }

View file

@ -2,6 +2,6 @@ namespace Ryujinx.Graphics.Texture
{ {
interface ISwizzle interface ISwizzle
{ {
int GetSwizzleOffset(int X, int Y); int GetSwizzleOffset(int X, int Y, int Z);
} }
} }

View file

@ -4,6 +4,7 @@ using Ryujinx.Graphics.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using System.Diagnostics;
namespace Ryujinx.Graphics.Texture namespace Ryujinx.Graphics.Texture
{ {
@ -24,14 +25,16 @@ namespace Ryujinx.Graphics.Texture
public int BytesPerPixel { get; private set; } public int BytesPerPixel { get; private set; }
public int BlockWidth { get; private set; } public int BlockWidth { get; private set; }
public int BlockHeight { get; private set; } public int BlockHeight { get; private set; }
public int BlockDepth { get; private set; }
public TargetBuffer Target { get; private set; } public TargetBuffer Target { get; private set; }
public ImageDescriptor(int BytesPerPixel, int BlockWidth, int BlockHeight, TargetBuffer Target) public ImageDescriptor(int BytesPerPixel, int BlockWidth, int BlockHeight, int BlockDepth, TargetBuffer Target)
{ {
this.BytesPerPixel = BytesPerPixel; this.BytesPerPixel = BytesPerPixel;
this.BlockWidth = BlockWidth; this.BlockWidth = BlockWidth;
this.BlockHeight = BlockHeight; this.BlockHeight = BlockHeight;
this.BlockDepth = BlockDepth;
this.Target = Target; this.Target = Target;
} }
} }
@ -93,52 +96,53 @@ namespace Ryujinx.Graphics.Texture
private static readonly Dictionary<GalImageFormat, ImageDescriptor> s_ImageTable = private static readonly Dictionary<GalImageFormat, ImageDescriptor> s_ImageTable =
new Dictionary<GalImageFormat, ImageDescriptor>() new Dictionary<GalImageFormat, ImageDescriptor>()
{ {
{ GalImageFormat.RGBA32, new ImageDescriptor(16, 1, 1, TargetBuffer.Color) }, // TODO: check if everything is alright here
{ GalImageFormat.RGBA16, new ImageDescriptor(8, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RGBA32, new ImageDescriptor(16, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.RG32, new ImageDescriptor(8, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RGBA16, new ImageDescriptor(8, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.RGBX8, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RG32, new ImageDescriptor(8, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.RGBA8, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RGBX8, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.BGRA8, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RGBA8, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.RGB10A2, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) }, { GalImageFormat.BGRA8, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.R32, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RGB10A2, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.RGBA4, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) }, { GalImageFormat.R32, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.BptcSfloat, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) }, { GalImageFormat.RGBA4, new ImageDescriptor(2, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.BptcUfloat, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) }, { GalImageFormat.BptcSfloat, new ImageDescriptor(16, 4, 4, 4, TargetBuffer.Color) },
{ GalImageFormat.BGR5A1, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) }, { GalImageFormat.BptcUfloat, new ImageDescriptor(16, 4, 4, 4, TargetBuffer.Color) },
{ GalImageFormat.RGB5A1, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) }, { GalImageFormat.BGR5A1, new ImageDescriptor(2, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.RGB565, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RGB5A1, new ImageDescriptor(2, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.BGR565, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RGB565, new ImageDescriptor(2, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.BptcUnorm, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) }, { GalImageFormat.BGR565, new ImageDescriptor(2, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.RG16, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) }, { GalImageFormat.BptcUnorm, new ImageDescriptor(16, 4, 4, 4, TargetBuffer.Color) },
{ GalImageFormat.RG8, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RG16, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.R16, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) }, { GalImageFormat.RG8, new ImageDescriptor(2, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.R8, new ImageDescriptor(1, 1, 1, TargetBuffer.Color) }, { GalImageFormat.R16, new ImageDescriptor(2, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.R11G11B10, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) }, { GalImageFormat.R8, new ImageDescriptor(1, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.BC1, new ImageDescriptor(8, 4, 4, TargetBuffer.Color) }, { GalImageFormat.R11G11B10, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Color) },
{ GalImageFormat.BC2, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) }, { GalImageFormat.BC1, new ImageDescriptor(8, 4, 4, 4, TargetBuffer.Color) },
{ GalImageFormat.BC3, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) }, { GalImageFormat.BC2, new ImageDescriptor(16, 4, 4, 4, TargetBuffer.Color) },
{ GalImageFormat.BC4, new ImageDescriptor(8, 4, 4, TargetBuffer.Color) }, { GalImageFormat.BC3, new ImageDescriptor(16, 4, 4, 4, TargetBuffer.Color) },
{ GalImageFormat.BC5, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) }, { GalImageFormat.BC4, new ImageDescriptor(8, 4, 4, 4, TargetBuffer.Color) },
{ GalImageFormat.Astc2D4x4, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) }, { GalImageFormat.BC5, new ImageDescriptor(16, 4, 4, 4, TargetBuffer.Color) },
{ GalImageFormat.Astc2D5x5, new ImageDescriptor(16, 5, 5, TargetBuffer.Color) }, { GalImageFormat.Astc2D4x4, new ImageDescriptor(16, 4, 4, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D6x6, new ImageDescriptor(16, 6, 6, TargetBuffer.Color) }, { GalImageFormat.Astc2D5x5, new ImageDescriptor(16, 5, 5, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D8x8, new ImageDescriptor(16, 8, 8, TargetBuffer.Color) }, { GalImageFormat.Astc2D6x6, new ImageDescriptor(16, 6, 6, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D10x10, new ImageDescriptor(16, 10, 10, TargetBuffer.Color) }, { GalImageFormat.Astc2D8x8, new ImageDescriptor(16, 8, 8, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D12x12, new ImageDescriptor(16, 12, 12, TargetBuffer.Color) }, { GalImageFormat.Astc2D10x10, new ImageDescriptor(16, 10, 10, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D5x4, new ImageDescriptor(16, 5, 4, TargetBuffer.Color) }, { GalImageFormat.Astc2D12x12, new ImageDescriptor(16, 12, 12, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D6x5, new ImageDescriptor(16, 6, 5, TargetBuffer.Color) }, { GalImageFormat.Astc2D5x4, new ImageDescriptor(16, 5, 4, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D8x6, new ImageDescriptor(16, 8, 6, TargetBuffer.Color) }, { GalImageFormat.Astc2D6x5, new ImageDescriptor(16, 6, 5, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D10x8, new ImageDescriptor(16, 10, 8, TargetBuffer.Color) }, { GalImageFormat.Astc2D8x6, new ImageDescriptor(16, 8, 6, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D12x10, new ImageDescriptor(16, 12, 10, TargetBuffer.Color) }, { GalImageFormat.Astc2D10x8, new ImageDescriptor(16, 10, 8, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D8x5, new ImageDescriptor(16, 8, 5, TargetBuffer.Color) }, { GalImageFormat.Astc2D12x10, new ImageDescriptor(16, 12, 10, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D10x5, new ImageDescriptor(16, 10, 5, TargetBuffer.Color) }, { GalImageFormat.Astc2D8x5, new ImageDescriptor(16, 8, 5, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D10x6, new ImageDescriptor(16, 10, 6, TargetBuffer.Color) }, { GalImageFormat.Astc2D10x5, new ImageDescriptor(16, 10, 5, 1, TargetBuffer.Color) },
{ GalImageFormat.Astc2D10x6, new ImageDescriptor(16, 10, 6, 1, TargetBuffer.Color) },
{ GalImageFormat.D16, new ImageDescriptor(2, 1, 1, TargetBuffer.Depth) }, { GalImageFormat.D16, new ImageDescriptor(2, 1, 1, 1, TargetBuffer.Depth) },
{ GalImageFormat.D24, new ImageDescriptor(4, 1, 1, TargetBuffer.Depth) }, { GalImageFormat.D24, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Depth) },
{ GalImageFormat.D24S8, new ImageDescriptor(4, 1, 1, TargetBuffer.DepthStencil) }, { GalImageFormat.D24S8, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.DepthStencil) },
{ GalImageFormat.D32, new ImageDescriptor(4, 1, 1, TargetBuffer.Depth) }, { GalImageFormat.D32, new ImageDescriptor(4, 1, 1, 1, TargetBuffer.Depth) },
{ GalImageFormat.D32S8, new ImageDescriptor(8, 1, 1, TargetBuffer.DepthStencil) } { GalImageFormat.D32S8, new ImageDescriptor(8, 1, 1, 1, TargetBuffer.DepthStencil) }
}; };
public static GalImageFormat ConvertTexture( public static GalImageFormat ConvertTexture(
@ -225,6 +229,7 @@ namespace Ryujinx.Graphics.Texture
throw new NotImplementedException(Format.ToString()); throw new NotImplementedException(Format.ToString());
} }
// TODO: non 2d
public static byte[] ReadTexture(IMemory Memory, GalImage Image, long Position) public static byte[] ReadTexture(IMemory Memory, GalImage Image, long Position)
{ {
MemoryManager CpuMemory; MemoryManager CpuMemory;
@ -238,52 +243,61 @@ namespace Ryujinx.Graphics.Texture
CpuMemory = (MemoryManager)Memory; CpuMemory = (MemoryManager)Memory;
} }
Debug.Assert(Image.TextureType == TextureType.TwoD, "non 2d texture read");
ISwizzle Swizzle = TextureHelper.GetSwizzle(Image); ISwizzle Swizzle = TextureHelper.GetSwizzle(Image);
ImageDescriptor Desc = GetImageDescriptor(Image.Format); ImageDescriptor Desc = GetImageDescriptor(Image.Format);
(int Width, int Height) = GetImageSizeInBlocks(Image); (int Width, int Height, int Depth) = GetImageSizeInBlocks(Image);
int BytesPerPixel = Desc.BytesPerPixel; int BytesPerPixel = Desc.BytesPerPixel;
//Note: Each row of the texture needs to be aligned to 4 bytes. //Note: Each row of the texture needs to be aligned to 4 bytes.
int Pitch = (Width * BytesPerPixel + 3) & ~3; int Pitch = (Width * BytesPerPixel + 3) & ~3;
byte[] Data = new byte[Height * Pitch]; byte[] Data = new byte[Height * Pitch * Depth];
for (int Z = 0; Z < Depth; Z++)
for (int Y = 0; Y < Height; Y++)
{ {
int OutOffs = Y * Pitch; for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++)
{ {
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); int OutOffs = Y * Pitch + (Z * Width * Height * BytesPerPixel);
CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel); for (int X = 0; X < Width; X++)
{
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y, Z);
OutOffs += BytesPerPixel; CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel);
OutOffs += BytesPerPixel;
}
} }
} }
return Data; return Data;
} }
// TODO: non 2d
public static void WriteTexture(NvGpuVmm Vmm, GalImage Image, long Position, byte[] Data) public static void WriteTexture(NvGpuVmm Vmm, GalImage Image, long Position, byte[] Data)
{ {
ISwizzle Swizzle = TextureHelper.GetSwizzle(Image); ISwizzle Swizzle = TextureHelper.GetSwizzle(Image);
ImageDescriptor Desc = GetImageDescriptor(Image.Format); ImageDescriptor Desc = GetImageDescriptor(Image.Format);
(int Width, int Height) = ImageUtils.GetImageSizeInBlocks(Image); (int Width, int Height, int Depth) = ImageUtils.GetImageSizeInBlocks(Image);
int BytesPerPixel = Desc.BytesPerPixel; int BytesPerPixel = Desc.BytesPerPixel;
int InOffs = 0; int InOffs = 0;
Debug.Assert(Image.TextureType == TextureType.TwoD, "non 2d texture write");
for (int Z = 0; Z < Depth; Z++)
for (int Y = 0; Y < Height; Y++) for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++) for (int X = 0; X < Width; X++)
{ {
long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y, Z);
Vmm.Memory.WriteBytes(Position + Offset, Data, InOffs, BytesPerPixel); Vmm.Memory.WriteBytes(Position + Offset, Data, InOffs, BytesPerPixel);
@ -291,6 +305,7 @@ namespace Ryujinx.Graphics.Texture
} }
} }
// TODO: SUPPORT NON 2D
public static bool CopyTexture( public static bool CopyTexture(
NvGpuVmm Vmm, NvGpuVmm Vmm,
GalImage SrcImage, GalImage SrcImage,
@ -319,8 +334,8 @@ namespace Ryujinx.Graphics.Texture
for (int Y = 0; Y < Height; Y++) for (int Y = 0; Y < Height; Y++)
for (int X = 0; X < Width; X++) for (int X = 0; X < Width; X++)
{ {
long SrcOffset = (uint)SrcSwizzle.GetSwizzleOffset(SrcX + X, SrcY + Y); long SrcOffset = (uint)SrcSwizzle.GetSwizzleOffset(SrcX + X, SrcY + Y, 0);
long DstOffset = (uint)DstSwizzle.GetSwizzleOffset(DstX + X, DstY + Y); long DstOffset = (uint)DstSwizzle.GetSwizzleOffset(DstX + X, DstY + Y, 0);
byte[] Texel = Vmm.ReadBytes(SrcAddress + SrcOffset, BytesPerPixel); byte[] Texel = Vmm.ReadBytes(SrcAddress + SrcOffset, BytesPerPixel);
@ -330,15 +345,31 @@ namespace Ryujinx.Graphics.Texture
return true; return true;
} }
// FIXME: Check if that does the trick
public static int GetSize(GalImage Image) public static int GetSize(GalImage Image)
{ {
ImageDescriptor Desc = GetImageDescriptor(Image.Format); ImageDescriptor Desc = GetImageDescriptor(Image.Format);
int ComponentCount = GetCoordsCountTextureType(Image.TextureType);
if (IsArray(Image.TextureType))
ComponentCount--;
int Width = DivRoundUp(Image.Width, Desc.BlockWidth); int Width = DivRoundUp(Image.Width, Desc.BlockWidth);
int Height = DivRoundUp(Image.Height, Desc.BlockHeight); int Height = DivRoundUp(Image.Height, Desc.BlockHeight);
int Depth = DivRoundUp(Image.Depth, Desc.BlockDepth);
// TODO: multi format switch (ComponentCount)
return Desc.BytesPerPixel * Width * Height; {
case 1:
return Desc.BytesPerPixel * Width;
case 2:
return Desc.BytesPerPixel * Width * Height;
case 3:
return Desc.BytesPerPixel * Width * Height * Depth;
default:
throw new InvalidOperationException();
}
} }
public static int GetPitch(GalImageFormat Format, int Width) public static int GetPitch(GalImageFormat Format, int Width)
@ -362,6 +393,11 @@ namespace Ryujinx.Graphics.Texture
return GetImageDescriptor(Format).BlockHeight; return GetImageDescriptor(Format).BlockHeight;
} }
public static int GetBlockDepth(GalImageFormat Format)
{
return GetImageDescriptor(Format).BlockDepth;
}
public static int GetAlignedWidth(GalImage Image) public static int GetAlignedWidth(GalImage Image)
{ {
ImageDescriptor Desc = GetImageDescriptor(Image.Format); ImageDescriptor Desc = GetImageDescriptor(Image.Format);
@ -380,12 +416,14 @@ namespace Ryujinx.Graphics.Texture
return (Image.Width + AlignMask) & ~AlignMask; return (Image.Width + AlignMask) & ~AlignMask;
} }
public static (int Width, int Height) GetImageSizeInBlocks(GalImage Image) // TODO: non 2d
public static (int Width, int Height, int Depth) GetImageSizeInBlocks(GalImage Image)
{ {
ImageDescriptor Desc = GetImageDescriptor(Image.Format); ImageDescriptor Desc = GetImageDescriptor(Image.Format);
return (DivRoundUp(Image.Width, Desc.BlockWidth), return (DivRoundUp(Image.Width, Desc.BlockWidth),
DivRoundUp(Image.Height, Desc.BlockHeight)); DivRoundUp(Image.Height, Desc.BlockHeight),
DivRoundUp(Image.Depth, Desc.BlockDepth));
} }
public static int GetBytesPerPixel(GalImageFormat Format) public static int GetBytesPerPixel(GalImageFormat Format)

View file

@ -5,15 +5,18 @@ namespace Ryujinx.Graphics.Texture
private int Pitch; private int Pitch;
private int Bpp; private int Bpp;
public LinearSwizzle(int Pitch, int Bpp) private int ZLayer;
public LinearSwizzle(int Pitch, int Bpp, int Width, int Height)
{ {
this.Pitch = Pitch; this.Pitch = Pitch;
this.Bpp = Bpp; this.Bpp = Bpp;
this.ZLayer = Width * Height * Bpp;
} }
public int GetSwizzleOffset(int X, int Y) public int GetSwizzleOffset(int X, int Y, int Z)
{ {
return X * Bpp + Y * Pitch; return Z * ZLayer + X * Bpp + Y * Pitch;
} }
} }
} }

View file

@ -2,6 +2,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory; using Ryujinx.Graphics.Memory;
using System; using System;
using System.Diagnostics;
namespace Ryujinx.Graphics.Texture namespace Ryujinx.Graphics.Texture
{ {
@ -22,6 +23,8 @@ namespace Ryujinx.Graphics.Texture
TextureSwizzle Swizzle = (TextureSwizzle)((Tic[2] >> 21) & 7); TextureSwizzle Swizzle = (TextureSwizzle)((Tic[2] >> 21) & 7);
int MaxMipmapLevel = (Tic[3] >> 28) & 0xF + 1;
GalMemoryLayout Layout; GalMemoryLayout Layout;
if (Swizzle == TextureSwizzle.BlockLinear || if (Swizzle == TextureSwizzle.BlockLinear ||
@ -44,6 +47,11 @@ namespace Ryujinx.Graphics.Texture
int Height = (Tic[5] & 0xffff) + 1; int Height = (Tic[5] & 0xffff) + 1;
int Depth = ((Tic[5] >> 16) & 0x3fff) + 1; int Depth = ((Tic[5] >> 16) & 0x3fff) + 1;
if (TextureType == TextureType.OneD)
{
Height = 1;
}
if (TextureType == TextureType.TwoD || TextureType == TextureType.OneD) if (TextureType == TextureType.TwoD || TextureType == TextureType.OneD)
{ {
Depth = 1; Depth = 1;
@ -58,6 +66,7 @@ namespace Ryujinx.Graphics.Texture
Layout, Layout,
Format, Format,
TextureType, TextureType,
MaxMipmapLevel,
XSource, XSource,
YSource, YSource,
ZSource, ZSource,

View file

@ -9,9 +9,11 @@ namespace Ryujinx.Graphics.Texture
public static ISwizzle GetSwizzle(GalImage Image) public static ISwizzle GetSwizzle(GalImage Image)
{ {
int BlockWidth = ImageUtils.GetBlockWidth (Image.Format); int BlockWidth = ImageUtils.GetBlockWidth (Image.Format);
int BlockHeight = ImageUtils.GetBlockHeight (Image.Format);
int BytesPerPixel = ImageUtils.GetBytesPerPixel(Image.Format); int BytesPerPixel = ImageUtils.GetBytesPerPixel(Image.Format);
int Width = (Image.Width + (BlockWidth - 1)) / BlockWidth; int Width = (Image.Width + (BlockWidth - 1)) / BlockWidth;
int Height = (Image.Height + (BlockHeight - 1)) / BlockHeight;
if (Image.Layout == GalMemoryLayout.BlockLinear) if (Image.Layout == GalMemoryLayout.BlockLinear)
{ {
@ -19,11 +21,11 @@ namespace Ryujinx.Graphics.Texture
Width = (Width + AlignMask) & ~AlignMask; Width = (Width + AlignMask) & ~AlignMask;
return new BlockLinearSwizzle(Width, BytesPerPixel, Image.GobBlockHeight); return new BlockLinearSwizzle(Width, Height, BytesPerPixel, Image.GobBlockHeight);
} }
else else
{ {
return new LinearSwizzle(Image.Pitch, BytesPerPixel); return new LinearSwizzle(Image.Pitch, BytesPerPixel, Width, Height);
} }
} }