Add the concept of layer count for array instead of using depth

Also cleanup GetGpuSize as Swizzle can compute the size with mipmap
This commit is contained in:
Thog 2019-02-17 15:23:40 +01:00
commit 5eda7ae7a8
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
10 changed files with 82 additions and 95 deletions

View file

@ -6,7 +6,10 @@ namespace Ryujinx.Graphics.Gal
{ {
public int Width; public int Width;
public int Height; public int Height;
// FIXME: separate layer and depth
public int Depth; public int Depth;
public int LayerCount;
public int TileWidth; public int TileWidth;
public int GobBlockHeight; public int GobBlockHeight;
public int GobBlockDepth; public int GobBlockDepth;
@ -25,6 +28,7 @@ namespace Ryujinx.Graphics.Gal
int Width, int Width,
int Height, int Height,
int Depth, int Depth,
int LayerCount,
int TileWidth, int TileWidth,
int GobBlockHeight, int GobBlockHeight,
int GobBlockDepth, int GobBlockDepth,
@ -39,6 +43,7 @@ namespace Ryujinx.Graphics.Gal
{ {
this.Width = Width; this.Width = Width;
this.Height = Height; this.Height = Height;
this.LayerCount = LayerCount;
this.Depth = Depth; this.Depth = Depth;
this.TileWidth = TileWidth; this.TileWidth = TileWidth;
this.GobBlockHeight = GobBlockHeight; this.GobBlockHeight = GobBlockHeight;

View file

@ -82,7 +82,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Type, Type,
IntPtr.Zero); IntPtr.Zero);
break; break;
case TextureTarget.Texture2DArray:
case TextureTarget.Texture3D: case TextureTarget.Texture3D:
GL.TexImage3D( GL.TexImage3D(
Target, Target,
@ -96,6 +95,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Type, Type,
IntPtr.Zero); IntPtr.Zero);
break; break;
case TextureTarget.Texture2DArray:
GL.TexImage3D(
Target,
Level,
InternalFmt,
Image.Width,
Image.Height,
Image.LayerCount,
Border,
Format,
Type,
IntPtr.Zero);
break;
case TextureTarget.TextureCubeMap: case TextureTarget.TextureCubeMap:
int FaceSize = ImageUtils.GetSize(Image) / Image.Depth; int FaceSize = ImageUtils.GetSize(Image) / Image.Depth;
@ -175,6 +187,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
case TextureTarget.TextureCubeMap: case TextureTarget.TextureCubeMap:
Span<byte> Array = new Span<byte>(Data); Span<byte> Array = new Span<byte>(Data);
// FIXME: wrong
int FaceSize = ImageUtils.GetSize(Image) / Image.Depth; int FaceSize = ImageUtils.GetSize(Image) / Image.Depth;
for (int Face = 0; Face < 6; Face++) for (int Face = 0; Face < 6; Face++)
@ -197,7 +210,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
InternalFmt, InternalFmt,
Image.Width, Image.Width,
Image.Height, Image.Height,
Image.Depth * 6, Image.LayerCount * 6,
Border, Border,
Data.Length, Data.Length,
Data); Data);
@ -257,7 +270,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Type, Type,
Data); Data);
break; break;
case TextureTarget.Texture2DArray:
case TextureTarget.Texture3D: case TextureTarget.Texture3D:
GL.TexImage3D( GL.TexImage3D(
Target, Target,
@ -271,9 +283,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Type, Type,
Data); Data);
break; break;
case TextureTarget.Texture2DArray:
GL.TexImage3D(
Target,
Level,
InternalFmt,
Image.Width,
Image.Height,
Image.LayerCount,
Border,
Format,
Type,
Data);
break;
case TextureTarget.TextureCubeMap: case TextureTarget.TextureCubeMap:
Span<byte> Array = new Span<byte>(Data); Span<byte> Array = new Span<byte>(Data);
// FIXME: wrong
int FaceSize = ImageUtils.GetSize(Image) / Image.Depth; int FaceSize = ImageUtils.GetSize(Image) / Image.Depth;
for (int Face = 0; Face < 6; Face++) for (int Face = 0; Face < 6; Face++)

View file

@ -1,3 +1,4 @@
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory; using Ryujinx.Graphics.Memory;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
@ -118,7 +119,7 @@ namespace Ryujinx.Graphics.Graphics3d
GalImage SrcTexture = new GalImage( GalImage SrcTexture = new GalImage(
SrcWidth, SrcWidth,
SrcHeight, SrcHeight,
SrcDepth, 1, 1, SrcDepth, 1,
SrcBlockHeight, 1, SrcBlockHeight, 1,
SrcLayout, SrcLayout,
SrcImgFormat, SrcImgFormat,
@ -127,7 +128,7 @@ namespace Ryujinx.Graphics.Graphics3d
GalImage DstTexture = new GalImage( GalImage DstTexture = new GalImage(
DstWidth, DstWidth,
DstHeight, DstHeight,
DstDepth, 1, 1, DstDepth, 1,
DstBlockHeight, 1, DstBlockHeight, 1,
DstLayout, DstLayout,
DstImgFormat, DstImgFormat,
@ -138,8 +139,7 @@ namespace Ryujinx.Graphics.Graphics3d
long GetLayerOffset(GalImage Image, int Layer) long GetLayerOffset(GalImage Image, int Layer)
{ {
// TODO: mip map return (ImageUtils.GetGpuSize(Image) / Image.LayerCount) * Layer;
return (ImageUtils.GetGpuSize(Image) / Image.Depth) * Layer;
} }
int SrcLayerIndex = -1; int SrcLayerIndex = -1;
@ -161,7 +161,7 @@ namespace Ryujinx.Graphics.Graphics3d
if (IsSrcLayered && SrcLayerIndex == -1) if (IsSrcLayered && SrcLayerIndex == -1)
{ {
for (int Layer = 0; Layer < SrcTexture.Depth; Layer++) for (int Layer = 0; Layer < SrcTexture.LayerCount; Layer++)
{ {
Gpu.ResourceManager.SetTextureArrayLayer(SrcKey + GetLayerOffset(SrcTexture, Layer), Layer); Gpu.ResourceManager.SetTextureArrayLayer(SrcKey + GetLayerOffset(SrcTexture, Layer), Layer);
} }
@ -171,7 +171,7 @@ namespace Ryujinx.Graphics.Graphics3d
if (IsDstLayered && DstLayerIndex == -1) if (IsDstLayered && DstLayerIndex == -1)
{ {
for (int Layer = 0; Layer < DstTexture.Depth; Layer++) for (int Layer = 0; Layer < DstTexture.LayerCount; Layer++)
{ {
Gpu.ResourceManager.SetTextureArrayLayer(DstKey + GetLayerOffset(DstTexture, Layer), Layer); Gpu.ResourceManager.SetTextureArrayLayer(DstKey + GetLayerOffset(DstTexture, Layer), Layer);
} }

View file

@ -208,7 +208,7 @@ namespace Ryujinx.Graphics.Graphics3d
GalImageFormat Format = ImageUtils.ConvertSurface((GalSurfaceFormat)SurfFormat); GalImageFormat Format = ImageUtils.ConvertSurface((GalSurfaceFormat)SurfFormat);
GalImage Image = new GalImage(Width, Height, 1, 1, GobBlockHeight, 1, Layout, Format, GalTextureTarget.TwoD); GalImage Image = new GalImage(Width, Height, 1, 1, 1, GobBlockHeight, 1, Layout, Format, GalTextureTarget.TwoD);
Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image); Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image);
@ -263,7 +263,7 @@ namespace Ryujinx.Graphics.Graphics3d
GalImageFormat Format = ImageUtils.ConvertZeta((GalZetaFormat)ZetaFormat); GalImageFormat Format = ImageUtils.ConvertZeta((GalZetaFormat)ZetaFormat);
// TODO: Support non 2D? // TODO: Support non 2D?
GalImage Image = new GalImage(Width, Height, 1, 1, GobBlockHeight, 1, Layout, Format, GalTextureTarget.TwoD); GalImage Image = new GalImage(Width, Height, 1, 1, 1, GobBlockHeight, 1, Layout, Format, GalTextureTarget.TwoD);
Gpu.ResourceManager.SendZetaBuffer(Vmm, Key, Image); Gpu.ResourceManager.SendZetaBuffer(Vmm, Key, Image);
} }
@ -609,7 +609,7 @@ namespace Ryujinx.Graphics.Graphics3d
{ {
//FIXME: Some games like puyo puyo will use handles with the value 0. //FIXME: Some games like puyo puyo will use handles with the value 0.
//This is a bug, most likely caused by sync issues. //This is a bug, most likely caused by sync issues.
return (0, default(GalImage), default(GalTextureSampler)); //return (0, default(GalImage), default(GalTextureSampler));
} }
bool LinkedTsc = ReadRegisterBool(NvGpuEngine3dReg.LinkedTsc); bool LinkedTsc = ReadRegisterBool(NvGpuEngine3dReg.LinkedTsc);

View file

@ -3,5 +3,11 @@ namespace Ryujinx.Graphics.Texture
interface ISwizzle interface ISwizzle
{ {
int GetSwizzleOffset(int X, int Y, int Z); int GetSwizzleOffset(int X, int Y, int Z);
void SetMipLevel(int Level);
int GetMipOffset(int Level);
int GetImageSize(int MipsCount);
} }
} }

View file

@ -364,89 +364,9 @@ namespace Ryujinx.Graphics.Texture
} }
} }
// from envytools
private static readonly int GobSizeX = 64;
private static readonly int GobSizeY = 8;
private static readonly int GobSizeZ = 1;
// https://github.com/mesa3d/mesa/blob/master/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c
// FIXME: the width is never set to anything, maybe there is other variants?
// TODO: miplevels
private static (int TileWidth, int TileHeight, int TileDepth) GetTileDimensions(GalImage Image)
{
(int Width, int Height, int Depth) = GetImageSizeInBlocks(Image);
int TileWidth = 0;
int TileHeight = 0;
int TileDepth = 0;
if (Height > 64)
{
TileHeight = 4;
}
else if (Height > 32)
{
TileHeight = 3;
}
else if (Height > 16)
{
TileHeight = 2;
}
else if (Height > 8)
{
TileHeight = 1;
}
if (Image.TextureTarget == GalTextureTarget.ThreeD)
{
if (TileHeight > 2)
{
TileHeight = 2;
}
if (Depth > 16 && TileDepth < 2)
{
TileDepth = 5;
}
else if (Depth > 8)
{
TileDepth = 4;
}
else if (Depth > 4)
{
TileDepth = 3;
}
else if (Depth > 2)
{
TileDepth = 2;
}
else if (Depth > 1)
{
TileDepth = 1;
}
}
return (GobSizeX << TileWidth, GobSizeY << TileHeight, GobSizeZ << TileDepth);
}
public static int GetGpuSize(GalImage Image, bool forcePitch = false) public static int GetGpuSize(GalImage Image, bool forcePitch = false)
{ {
ImageDescriptor Desc = GetImageDescriptor(Image.Format); return TextureHelper.GetSwizzle(Image).GetImageSize(Image.MaxMipmapLevel) * Image.LayerCount;
if (Image.Layout == GalMemoryLayout.Pitch || forcePitch)
{
// TODO: check this
return Image.Width * Image.Height * Image.Depth * Desc.BytesPerPixel;
}
(int TileWidth, int TileHeight, int TileDepth) = GetTileDimensions(Image);
(int BlockX, int BlockY, int _) = GetImageSizeInBlocks(Image);
int Pitch = BitUtils.AlignUp(BlockX * Desc.BytesPerPixel, TileWidth);
int Height = BitUtils.AlignUp(BlockY, TileHeight);
int Depth = BitUtils.AlignUp(Image.Depth, TileDepth);
return BitUtils.AlignUp(Pitch * Height * Depth, (GobSizeX * GobSizeY) << (TileWidth + TileHeight + TileDepth));
} }
public static int GetPitch(GalImageFormat Format, int Width) public static int GetPitch(GalImageFormat Format, int Width)

View file

@ -1,3 +1,5 @@
using System;
namespace Ryujinx.Graphics.Texture namespace Ryujinx.Graphics.Texture
{ {
class LinearSwizzle : ISwizzle class LinearSwizzle : ISwizzle
@ -14,6 +16,23 @@ namespace Ryujinx.Graphics.Texture
SliceSize = Width * Height * Bpp; SliceSize = Width * Height * Bpp;
} }
public void SetMipLevel(int Level)
{
throw new NotImplementedException();
}
public int GetMipOffset(int Level)
{
throw new NotImplementedException();
}
public int GetImageSize(int MipsCount)
{
if (MipsCount == 1)
return SliceSize;
throw new NotImplementedException();
}
public int GetSwizzleOffset(int X, int Y, int Z) public int GetSwizzleOffset(int X, int Y, int Z)
{ {
return Z * SliceSize + X * Bpp + Y * Pitch; return Z * SliceSize + X * Bpp + Y * Pitch;

View file

@ -47,6 +47,15 @@ namespace Ryujinx.Graphics.Texture
int Height = ((Tic[5] >> 0) & 0xffff) + 1; int Height = ((Tic[5] >> 0) & 0xffff) + 1;
int Depth = ((Tic[5] >> 16) & 0x3fff) + 1; int Depth = ((Tic[5] >> 16) & 0x3fff) + 1;
int LayoutCount = 1;
// TODO: check this
if (ImageUtils.IsArray(TextureTarget))
{
LayoutCount = Depth;
Depth = 1;
}
if (TextureTarget == GalTextureTarget.OneD) if (TextureTarget == GalTextureTarget.OneD)
{ {
Height = 1; Height = 1;
@ -58,6 +67,7 @@ namespace Ryujinx.Graphics.Texture
} }
else if (TextureTarget == GalTextureTarget.CubeMap) else if (TextureTarget == GalTextureTarget.CubeMap)
{ {
// TODO: WRONG
Depth = 6; Depth = 6;
} }
@ -65,6 +75,7 @@ namespace Ryujinx.Graphics.Texture
Width, Width,
Height, Height,
Depth, Depth,
LayoutCount,
TileWidth, TileWidth,
GobBlockHeight, GobBlockHeight,
GobBlockDepth, GobBlockDepth,

View file

@ -216,7 +216,7 @@ namespace Ryujinx.Graphics.VDec
GalImage Image = new GalImage( GalImage Image = new GalImage(
OutputConfig.SurfaceWidth, OutputConfig.SurfaceWidth,
OutputConfig.SurfaceHeight, 1, 1, OutputConfig.SurfaceHeight, 1, 1, 1,
OutputConfig.GobBlockHeight, 1, OutputConfig.GobBlockHeight, 1,
GalMemoryLayout.BlockLinear, GalMemoryLayout.BlockLinear,
GalImageFormat.RGBA8 | GalImageFormat.Unorm, GalImageFormat.RGBA8 | GalImageFormat.Unorm,

View file

@ -416,7 +416,7 @@ namespace Ryujinx.HLE.HOS.Services.Android
{ {
image = new GalImage( image = new GalImage(
fbWidth, fbWidth,
fbHeight, 1, 1, BlockHeight, 1, fbHeight, 1, 1, 1, BlockHeight, 1,
GalMemoryLayout.BlockLinear, GalMemoryLayout.BlockLinear,
imageFormat, imageFormat,
GalTextureTarget.TwoD); GalTextureTarget.TwoD);