Support depth in read/writeTexture
Also support WrapR and detect mipmap
This commit is contained in:
parent
f426de7e15
commit
5f0da0245e
13 changed files with 206 additions and 103 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++]);
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ namespace Ryujinx.Graphics.Texture
|
|||
|
||||
if (BlockZ != 1 || Z != 1)
|
||||
{
|
||||
// TODO: support 3D textures?
|
||||
throw new ASTCDecoderException("3D compressed textures unsupported!");
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,6 @@ namespace Ryujinx.Graphics.Texture
|
|||
{
|
||||
interface ISwizzle
|
||||
{
|
||||
int GetSwizzleOffset(int X, int Y);
|
||||
int GetSwizzleOffset(int X, int Y, int Z);
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue