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

View file

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

View file

@ -2,6 +2,7 @@ using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Texture;
using System;
using System.Diagnostics;
namespace Ryujinx.Graphics.Gal.OpenGL
{
@ -46,6 +47,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0;
Debug.Assert(Image.MaxMipmapLevel != 1, "No Mipmap support");
TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size);
if (ImageUtils.IsCompressed(Image.Format))
@ -87,7 +90,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
break;
default:
Logger.PrintWarning(LogClass.Gpu, $"Unsupported texture target type: {Target}");
//throw new InvalidOperationException();
throw new InvalidOperationException();
GL.TexImage2D(
TextureTarget.Texture2D,
Level,
@ -115,6 +118,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0;
Debug.Assert(Image.MaxMipmapLevel != 1, "No Mipmap support");
TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
if (ImageUtils.IsCompressed(Image.Format) && !IsAstc(Image.Format))
@ -195,14 +200,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format);
int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format);
int TextureBlockDepth = ImageUtils.GetBlockDepth(Image.Format);
// TODO: support 3D textures
Data = ASTCDecoder.DecodeToRGBA8888(
Data,
TextureBlockWidth,
TextureBlockHeight, 1,
TextureBlockHeight,
TextureBlockDepth,
Image.Width,
Image.Height, 1);
Image.Height,
Image.Depth);
Image.Format = GalImageFormat.RGBA8 | (Image.Format & GalImageFormat.TypeMask);
}
@ -211,16 +218,50 @@ namespace Ryujinx.Graphics.Gal.OpenGL
PixelFormat Format,
PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
GL.TexImage2D(
TextureTarget.Texture2D,
Level,
InternalFmt,
Image.Width,
Image.Height,
Border,
Format,
Type,
Data);
switch (Target)
{
case TextureTarget.Texture2D:
GL.TexImage2D(
Target,
Level,
InternalFmt,
Image.Width,
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 WrapT = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressV);
int WrapR = (int)OGLEnumConverter.GetTextureWrapMode(Sampler.AddressP);
int MinFilter = (int)OGLEnumConverter.GetTextureMinFilter(Sampler.MinFilter, Sampler.MipFilter);
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.TextureWrapT, WrapT);
GL.TexParameter(Target, TextureParameterName.TextureWrapR, WrapR);
GL.TexParameter(Target, TextureParameterName.TextureMinFilter, MinFilter);
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)
{
CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation);
@ -82,8 +83,6 @@ namespace Ryujinx.Graphics.Graphics3d
long SrcKey = Vmm.GetPhysicalAddress(SrcAddress);
long DstKey = Vmm.GetPhysicalAddress(DstAddress);
// TODO: all texture types
GalImage SrcTexture = new GalImage(
SrcWidth,
SrcHeight, 1, 1,

View file

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

View file

@ -119,14 +119,14 @@ namespace Ryujinx.Graphics.Graphics3d
}
else
{
BlockLinearSwizzle Swizzle = new BlockLinearSwizzle(CopyWidth, 1, CopyGobBlockHeight);
BlockLinearSwizzle Swizzle = new BlockLinearSwizzle(CopyWidth, CopyHeight, 1, CopyGobBlockHeight);
int SrcOffset = 0;
for (int Y = CopyStartY; Y < CopyHeight && SrcOffset < CopySize; Y++)
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++]);
}

View file

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

View file

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

View file

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

View file

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

View file

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