Initial non 2D textures support

- Shaders still need to be changed
- Some types aren't yet implemented
This commit is contained in:
Thog 2018-11-06 23:21:37 +01:00
commit b9a8380ac5
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
16 changed files with 460 additions and 68 deletions

View file

@ -6,6 +6,7 @@ namespace Ryujinx.Graphics.Gal
{ {
public int Width; public int Width;
public int Height; public int Height;
public int Depth;
public int TileWidth; public int TileWidth;
public int GobBlockHeight; public int GobBlockHeight;
public int Pitch; public int Pitch;
@ -16,14 +17,17 @@ namespace Ryujinx.Graphics.Gal
public GalTextureSource YSource; public GalTextureSource YSource;
public GalTextureSource ZSource; public GalTextureSource ZSource;
public GalTextureSource WSource; public GalTextureSource WSource;
public TextureType TextureType;
public GalImage( public GalImage(
int Width, int Width,
int Height, int Height,
int Depth,
int TileWidth, int TileWidth,
int GobBlockHeight, int GobBlockHeight,
GalMemoryLayout Layout, GalMemoryLayout Layout,
GalImageFormat Format, GalImageFormat Format,
TextureType TextureType,
GalTextureSource XSource = GalTextureSource.Red, GalTextureSource XSource = GalTextureSource.Red,
GalTextureSource YSource = GalTextureSource.Green, GalTextureSource YSource = GalTextureSource.Green,
GalTextureSource ZSource = GalTextureSource.Blue, GalTextureSource ZSource = GalTextureSource.Blue,
@ -31,6 +35,7 @@ namespace Ryujinx.Graphics.Gal
{ {
this.Width = Width; this.Width = Width;
this.Height = Height; this.Height = Height;
this.Depth = Depth;
this.TileWidth = TileWidth; this.TileWidth = TileWidth;
this.GobBlockHeight = GobBlockHeight; this.GobBlockHeight = GobBlockHeight;
this.Layout = Layout; this.Layout = Layout;
@ -39,6 +44,7 @@ namespace Ryujinx.Graphics.Gal
this.YSource = YSource; this.YSource = YSource;
this.ZSource = ZSource; this.ZSource = ZSource;
this.WSource = WSource; this.WSource = WSource;
this.TextureType = TextureType;
Pitch = ImageUtils.GetPitch(Format, Width); Pitch = ImageUtils.GetPitch(Format, Width);
} }

View file

@ -13,6 +13,6 @@ namespace Ryujinx.Graphics.Gal
void Bind(long Key, int Index, GalImage Image); void Bind(long Key, int Index, GalImage Image);
void SetSampler(GalTextureSampler Sampler); void SetSampler(GalImage Image, GalTextureSampler Sampler);
} }
} }

View file

@ -477,9 +477,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
(_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format); (_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format);
GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle); TextureTarget Target = ImageUtils.GetTextureTarget(NewImage.TextureType);
GL.GetTexImage(TextureTarget.Texture2D, 0, Format, Type, IntPtr.Zero); GL.BindTexture(Target, CachedImage.Handle);
GL.GetTexImage(Target, 0, Format, Type, IntPtr.Zero);
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0); GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO); GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO);

View file

@ -1,4 +1,5 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
using System; using System;
@ -38,7 +39,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
int Handle = GL.GenTexture(); int Handle = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, Handle); TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureType);
GL.BindTexture(Target, Handle);
const int Level = 0; //TODO: Support mipmap textures. const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0; const int Border = 0;
@ -54,23 +57,60 @@ namespace Ryujinx.Graphics.Gal.OpenGL
PixelFormat Format, PixelFormat Format,
PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format); PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
GL.TexImage2D( switch (Target)
TextureTarget.Texture2D, {
Level, case TextureTarget.Texture2D:
InternalFmt, GL.TexImage2D(
Image.Width, Target,
Image.Height, Level,
Border, InternalFmt,
Format, Image.Width,
Type, Image.Height,
IntPtr.Zero); Border,
Format,
Type,
IntPtr.Zero);
break;
case TextureTarget.Texture2DArray:
case TextureTarget.Texture3D:
GL.TexImage3D(
Target,
Level,
InternalFmt,
Image.Width,
Image.Height,
Image.Depth,
Border,
Format,
Type,
IntPtr.Zero);
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,
IntPtr.Zero);
break;
}
} }
public void Create(long Key, byte[] Data, GalImage Image) public void Create(long Key, byte[] Data, GalImage Image)
{ {
int Handle = GL.GenTexture(); int Handle = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, Handle); TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureType);
GL.BindTexture(Target, Handle);
const int Level = 0; //TODO: Support mipmap textures. const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0; const int Border = 0;
@ -81,15 +121,72 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format); InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
GL.CompressedTexImage2D( switch (Target)
TextureTarget.Texture2D, {
Level, case TextureTarget.Texture2D:
InternalFmt, GL.CompressedTexImage2D(
Image.Width, Target,
Image.Height, Level,
Border, InternalFmt,
Data.Length, Image.Width,
Data); Image.Height,
Border,
Data.Length,
Data);
break;
case TextureTarget.Texture2DArray:
case TextureTarget.Texture3D:
GL.CompressedTexImage3D(
Target,
Level,
InternalFmt,
Image.Width,
Image.Height,
Image.Depth,
Border,
Data.Length,
Data);
break;
case TextureTarget.TextureCubeMap:
for (int i = 0; i < 6; i++)
{
GL.CompressedTexImage2D(
TextureTarget.TextureCubeMapPositiveX + i,
Level,
InternalFmt,
Image.Width,
Image.Height,
Border,
Data.Length, // FIXME: NOT SURE OF THIS
Data);
}
break;
case TextureTarget.TextureCubeMapArray:
GL.CompressedTexImage3D(
Target,
Level,
InternalFmt,
Image.Width,
Image.Height,
Image.Depth * 6,
Border,
Data.Length,
Data);
break;
default:
Logger.PrintWarning(LogClass.Gpu, $"Unsupported texture target type: {Target} ({Image.Depth})");
throw new InvalidOperationException();
GL.CompressedTexImage2D(
TextureTarget.Texture2D,
Level,
InternalFmt,
Image.Width,
Image.Height,
Border,
Data.Length,
Data);
break;
}
} }
else else
{ {
@ -99,6 +196,7 @@ 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);
// TODO: support 3D textures
Data = ASTCDecoder.DecodeToRGBA8888( Data = ASTCDecoder.DecodeToRGBA8888(
Data, Data,
TextureBlockWidth, TextureBlockWidth,
@ -165,7 +263,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
GL.ActiveTexture(TextureUnit.Texture0 + Index); GL.ActiveTexture(TextureUnit.Texture0 + Index);
GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle); TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureType);
GL.BindTexture(Target, CachedImage.Handle);
int[] SwizzleRgba = new int[] int[] SwizzleRgba = new int[]
{ {
@ -175,11 +275,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
(int)OGLEnumConverter.GetTextureSwizzle(Image.WSource) (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource)
}; };
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, SwizzleRgba); GL.TexParameter(Target, TextureParameterName.TextureSwizzleRgba, SwizzleRgba);
} }
} }
public void SetSampler(GalTextureSampler Sampler) public void SetSampler(GalImage Image, GalTextureSampler Sampler)
{ {
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);
@ -187,11 +287,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, WrapS); TextureTarget Target = ImageUtils.GetTextureTarget(Image.TextureType);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, WrapT);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter); GL.TexParameter(Target, TextureParameterName.TextureWrapS, WrapS);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter); GL.TexParameter(Target, TextureParameterName.TextureWrapT, WrapT);
GL.TexParameter(Target, TextureParameterName.TextureMinFilter, MinFilter);
GL.TexParameter(Target, TextureParameterName.TextureMagFilter, MagFilter);
float[] Color = new float[] float[] Color = new float[]
{ {
@ -201,7 +303,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Sampler.BorderColor.Alpha Sampler.BorderColor.Alpha
}; };
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color); GL.TexParameter(Target, TextureParameterName.TextureBorderColor, Color);
} }
} }
} }

View file

@ -1,3 +1,5 @@
using Ryujinx.Graphics.Gal.OpenGL;
using Ryujinx.Graphics.Texture;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -232,7 +234,19 @@ namespace Ryujinx.Graphics.Gal.Shader
string Name = StagePrefix + TextureName + Index; string Name = StagePrefix + TextureName + Index;
m_Textures.TryAdd(Handle, new ShaderDeclInfo(Name, Handle)); TextureType TextureType;
// TODO: non 2d texture type for TEXQ?
if (Op.Inst == ShaderIrInst.Texq)
{
TextureType = TextureType.TwoD;
}
else
{
TextureType = ((ShaderIrMetaTex)Op.MetaData).TextureType;
}
m_Textures.TryAdd(Handle, new ShaderDeclInfo(Name, Handle, false, 0, 1, TextureType));
} }
else if (Op.Inst == ShaderIrInst.Texb) else if (Op.Inst == ShaderIrInst.Texb)
{ {
@ -259,7 +273,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
string Name = StagePrefix + TextureName + "_cb" + Cbuf.Index + "_" + Cbuf.Pos; string Name = StagePrefix + TextureName + "_cb" + Cbuf.Index + "_" + Cbuf.Pos;
m_CbTextures.Add(Op, new ShaderDeclInfo(Name, Cbuf.Pos, true, Cbuf.Index)); m_CbTextures.Add(Op, new ShaderDeclInfo(Name, Cbuf.Pos, true, Cbuf.Index, 1, ((ShaderIrMetaTex)Op.MetaData).TextureType));
} }
else else
{ {

View file

@ -1,3 +1,5 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.Texture;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -219,14 +221,52 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
private string GetSamplerType(TextureTarget TextureTarget)
{
switch (TextureTarget)
{
case TextureTarget.Texture1D:
return "sampler1D";
case TextureTarget.Texture2D:
return "sampler2D";
case TextureTarget.Texture3D:
return "sampler3D";
case TextureTarget.TextureCubeMap:
return "samplerCube";
case TextureTarget.TextureRectangle:
return "sampler2DRect";
case TextureTarget.Texture1DArray:
return "sampler1DArray";
case TextureTarget.Texture2DArray:
return "sampler2DArray";
case TextureTarget.TextureCubeMapArray:
return "samplerCubeArray";
case TextureTarget.TextureBuffer:
return "samplerBuffer";
case TextureTarget.Texture2DMultisample:
return "sampler2DMS";
case TextureTarget.Texture2DMultisampleArray:
return "sampler2DMSArray";
default:
throw new NotSupportedException();
}
}
private void PrintDeclTextures() private void PrintDeclTextures()
{ {
foreach (ShaderDeclInfo DeclInfo in IterateCbTextures()) foreach (ShaderDeclInfo DeclInfo in IterateCbTextures())
{ {
SB.AppendLine("uniform sampler2D " + DeclInfo.Name + ";"); TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType);
SB.AppendLine("uniform " + GetSamplerType(Target) + " " + DeclInfo.Name + ";");
} }
PrintDecls(Decl.Textures, "uniform sampler2D"); foreach (ShaderDeclInfo DeclInfo in Decl.Textures.Values.OrderBy(DeclKeySelector))
{
TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType);
SB.AppendLine("uniform " + GetSamplerType(Target) + " " + DeclInfo.Name + ";");
}
} }
private IEnumerable<ShaderDeclInfo> IterateCbTextures() private IEnumerable<ShaderDeclInfo> IterateCbTextures()
@ -1246,8 +1286,23 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetTexSamplerCoords(ShaderIrOp Op) private string GetTexSamplerCoords(ShaderIrOp Op)
{ {
return "vec2(" + GetOperExpr(Op, Op.OperandA) + ", " + ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData;
GetOperExpr(Op, Op.OperandB) + ")";
switch (Meta.TextureType)
{
case TextureType.OneD:
return GetOperExpr(Op, Meta.Coordinates[0]);
case TextureType.ThreeD:
case TextureType.TwoDArray:
case TextureType.CubeMap:
return "vec3(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + GetOperExpr(Op, Meta.Coordinates[1]) + ", " + GetOperExpr(Op, Meta.Coordinates[2]) + ")";
case TextureType.CubeArray:
return "vec4(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + GetOperExpr(Op, Meta.Coordinates[1]) + ", " + GetOperExpr(Op, Meta.Coordinates[2]) + ", " + GetOperExpr(Op, Meta.Coordinates[3]) + ")";
case TextureType.TwoD:
default:
return "vec2(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + GetOperExpr(Op, Meta.Coordinates[1]) + ")";
}
} }
private string GetITexSamplerCoords(ShaderIrOp Op) private string GetITexSamplerCoords(ShaderIrOp Op)

View file

@ -1,3 +1,4 @@
using Ryujinx.Graphics.Texture;
using System; using System;
using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper; using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper;
@ -29,6 +30,68 @@ namespace Ryujinx.Graphics.Gal.Shader
{ RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ } { RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ }
}; };
private static TextureType TexToTextureType(int TexType)
{
switch (TexType)
{
case 2:
return TextureType.TwoD;
case 4:
return TextureType.ThreeD;
case 6:
return TextureType.CubeMap;
default:
throw new InvalidOperationException();
}
}
private static int GetCoordsCountTextureType(TextureType TextureType)
{
switch (TextureType)
{
case TextureType.OneD:
return 1;
case TextureType.OneDArray:
case TextureType.TwoD:
case TextureType.TwoDNoMipMap:
return 2;
case TextureType.ThreeD:
case TextureType.TwoDArray:
case TextureType.CubeMap:
return 3;
default:
throw new NotImplementedException($"TEX of TextureTpe.{TextureType} not implemented");
}
}
private static TextureType TexsToTextureType(int TexType)
{
switch (TexType)
{
case 0:
return TextureType.OneD;
case 2:
case 4:
case 6:
case 8:
case 0xa:
case 0xc:
return TextureType.TwoD;
case 0xe:
case 0x10:
case 0x12:
return TextureType.TwoDArray;
case 0x14:
case 0x16:
return TextureType.ThreeD;
case 0x18:
case 0x1a:
return TextureType.CubeArray;
default:
throw new InvalidOperationException();
}
}
public static void Ld_A(ShaderIrBlock Block, long OpCode, int Position) public static void Ld_A(ShaderIrBlock Block, long OpCode, int Position)
{ {
ShaderIrNode[] Opers = OpCode.Abuf20(); ShaderIrNode[] Opers = OpCode.Abuf20();
@ -142,8 +205,12 @@ namespace Ryujinx.Graphics.Gal.Shader
private static void EmitTex(ShaderIrBlock Block, long OpCode, bool GprHandle) private static void EmitTex(ShaderIrBlock Block, long OpCode, bool GprHandle)
{ {
//TODO: Support other formats. // TODO: Support array textures
ShaderIrOperGpr[] Coords = new ShaderIrOperGpr[2]; TextureType TextureType = TexToTextureType(OpCode.Read(28, 6));
Block.AddNode(new ShaderIrCmnt($"TextureType: {TextureType}"));
// FIXME: check if this is right
ShaderIrOperGpr[] Coords = new ShaderIrOperGpr[GetCoordsCountTextureType(TextureType)];
for (int Index = 0; Index < Coords.Length; Index++) for (int Index = 0; Index < Coords.Length; Index++)
{ {
@ -187,7 +254,7 @@ namespace Ryujinx.Graphics.Gal.Shader
continue; continue;
} }
ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch); ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch, TextureType, Coords);
ShaderIrOp Op = new ShaderIrOp(Inst, Coords[0], Coords[1], OperC, Meta); ShaderIrOp Op = new ShaderIrOp(Inst, Coords[0], Coords[1], OperC, Meta);
@ -207,7 +274,73 @@ namespace Ryujinx.Graphics.Gal.Shader
private static void EmitTexs(ShaderIrBlock Block, long OpCode, ShaderIrInst Inst) private static void EmitTexs(ShaderIrBlock Block, long OpCode, ShaderIrInst Inst)
{ {
TextureType TextureType = TexsToTextureType(OpCode.Read(52, 0x1e));
Block.AddNode(new ShaderIrCmnt($"TextureType: {TextureType}"));
if (Inst == ShaderIrInst.Txlf && TextureType == TextureType.CubeArray)
{
throw new InvalidOperationException("TXLF instructions cannot use CUBE modifier!");
}
//TODO: Support other formats. //TODO: Support other formats.
ShaderIrOperGpr OperA = OpCode.Gpr8();
ShaderIrOperGpr OperB = OpCode.Gpr20();
ShaderIrOperGpr[] GetCoordinates()
{
ShaderIrOperGpr X;
ShaderIrOperGpr Y;
ShaderIrOperGpr Z;
ShaderIrOperGpr Index;
switch (TextureType)
{
case TextureType.OneD:
X = OperA;
return CoordsRegistersToTempRegisters(Block, X);
case TextureType.TwoDArray:
Index = OperA;
X = OpCode.Gpr8();
X.Index++;
Y = OperB;
return CoordsRegistersToTempRegisters(Block, X, Y, Index);
case TextureType.ThreeD:
case TextureType.CubeMap:
X = OperA;
Y = OpCode.Gpr8();
Y.Index += 1;
Z = OperB;
return CoordsRegistersToTempRegisters(Block, X, Y, Z);
case TextureType.CubeArray:
Index = OperA;
X = OpCode.Gpr8();
X.Index += 1;
Y = OpCode.Gpr8();
Y.Index += 2;
Z = OperB;
return CoordsRegistersToTempRegisters(Block, X, Y, Z, Index);
case TextureType.TwoD:
X = OperA;
Y = OperB;
return new ShaderIrOperGpr[] { X, Y };
default:
throw new NotImplementedException($"TEXS of TextureType.{TextureType} not supported!");
}
}
int LutIndex; int LutIndex;
LutIndex = !OpCode.Gpr0().IsConst ? 1 : 0; LutIndex = !OpCode.Gpr0().IsConst ? 1 : 0;
@ -277,12 +410,6 @@ namespace Ryujinx.Graphics.Gal.Shader
ShaderIrNode OperC = OpCode.Imm13_36(); ShaderIrNode OperC = OpCode.Imm13_36();
ShaderIrOperGpr Coord0 = ShaderIrOperGpr.MakeTemporary(0);
ShaderIrOperGpr Coord1 = ShaderIrOperGpr.MakeTemporary(1);
Block.AddNode(new ShaderIrAsg(Coord0, OpCode.Gpr8()));
Block.AddNode(new ShaderIrAsg(Coord1, OpCode.Gpr20()));
for (int Ch = 0; Ch < 4; Ch++) for (int Ch = 0; Ch < 4; Ch++)
{ {
if (!IsChannelUsed(ChMask, Ch)) if (!IsChannelUsed(ChMask, Ch))
@ -290,9 +417,9 @@ namespace Ryujinx.Graphics.Gal.Shader
continue; continue;
} }
ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch); ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch, TextureType, GetCoordinates());
ShaderIrOp Op = new ShaderIrOp(Inst, Coord0, Coord1, OperC, Meta); ShaderIrOp Op = new ShaderIrOp(Inst, OperA, OperB, OperC, Meta);
ShaderIrOperGpr Dst = GetDst(); ShaderIrOperGpr Dst = GetDst();
@ -307,5 +434,18 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
return (ChMask & (1 << Ch)) != 0; return (ChMask & (1 << Ch)) != 0;
} }
private static ShaderIrOperGpr[] CoordsRegistersToTempRegisters(ShaderIrBlock Block, params ShaderIrOperGpr[] Registers)
{
ShaderIrOperGpr[] Res = new ShaderIrOperGpr[Registers.Length];
for (int Index = 0; Index < Res.Length; Index++)
{
Res[Index] = ShaderIrOperGpr.MakeTemporary(Index);
Block.AddNode(new ShaderIrAsg(Res[Index], Registers[Index]));
}
return Res;
}
} }
} }

View file

@ -1,12 +1,18 @@
using Ryujinx.Graphics.Texture;
namespace Ryujinx.Graphics.Gal.Shader namespace Ryujinx.Graphics.Gal.Shader
{ {
class ShaderIrMetaTex : ShaderIrMeta class ShaderIrMetaTex : ShaderIrMeta
{ {
public int Elem { get; private set; } public int Elem { get; private set; }
public TextureType TextureType { get; private set; }
public ShaderIrNode[] Coordinates { get; private set; }
public ShaderIrMetaTex(int Elem) public ShaderIrMetaTex(int Elem, TextureType TextureType, params ShaderIrNode[] Coordinates)
{ {
this.Elem = Elem; this.Elem = Elem;
this.TextureType = TextureType;
this.Coordinates = Coordinates;
} }
} }
} }

View file

@ -1,3 +1,5 @@
using Ryujinx.Graphics.Texture;
namespace Ryujinx.Graphics.Gal namespace Ryujinx.Graphics.Gal
{ {
public class ShaderDeclInfo public class ShaderDeclInfo
@ -9,18 +11,22 @@ namespace Ryujinx.Graphics.Gal
public int Cbuf { get; private set; } public int Cbuf { get; private set; }
public int Size { get; private set; } public int Size { get; private set; }
public TextureType TextureType { get; private set; }
public ShaderDeclInfo( public ShaderDeclInfo(
string Name, string Name,
int Index, int Index,
bool IsCb = false, bool IsCb = false,
int Cbuf = 0, int Cbuf = 0,
int Size = 1) int Size = 1,
TextureType TextureType = TextureType.TwoD)
{ {
this.Name = Name; this.Name = Name;
this.Index = Index; this.Index = Index;
this.IsCb = IsCb; this.IsCb = IsCb;
this.Cbuf = Cbuf; this.Cbuf = Cbuf;
this.Size = Size; this.Size = Size;
this.TextureType = TextureType;
} }
internal void Enlarge(int NewSize) internal void Enlarge(int NewSize)

View file

@ -82,19 +82,23 @@ 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, SrcHeight, 1, 1,
SrcBlockHeight, SrcBlockHeight,
SrcLayout, SrcLayout,
SrcImgFormat); SrcImgFormat,
TextureType.TwoD);
GalImage DstTexture = new GalImage( GalImage DstTexture = new GalImage(
DstWidth, DstWidth,
DstHeight, 1, DstHeight, 1, 1,
DstBlockHeight, DstBlockHeight,
DstLayout, DstLayout,
DstImgFormat); DstImgFormat,
TextureType.TwoD);
SrcTexture.Pitch = SrcPitch; SrcTexture.Pitch = SrcPitch;
DstTexture.Pitch = DstPitch; DstTexture.Pitch = DstPitch;

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, GobBlockHeight, Layout, Format); GalImage Image = new GalImage(Width, Height, 1, 1, GobBlockHeight, Layout, Format, TextureType.TwoD);
Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image); Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image);
@ -262,7 +262,8 @@ namespace Ryujinx.Graphics.Graphics3d
GalImageFormat Format = ImageUtils.ConvertZeta((GalZetaFormat)ZetaFormat); GalImageFormat Format = ImageUtils.ConvertZeta((GalZetaFormat)ZetaFormat);
GalImage Image = new GalImage(Width, Height, 1, GobBlockHeight, Layout, Format); // TODO: all texture types
GalImage Image = new GalImage(Width, Height, 1, 1, GobBlockHeight, Layout, Format, TextureType.TwoD);
Gpu.ResourceManager.SendZetaBuffer(Vmm, Key, Image); Gpu.ResourceManager.SendZetaBuffer(Vmm, Key, Image);
} }
@ -598,7 +599,7 @@ namespace Ryujinx.Graphics.Graphics3d
} }
Gpu.Renderer.Texture.Bind(Key, Index, Image); Gpu.Renderer.Texture.Bind(Key, Index, Image);
Gpu.Renderer.Texture.SetSampler(Sampler); Gpu.Renderer.Texture.SetSampler(Image, Sampler);
} }
} }

View file

@ -3,6 +3,7 @@ using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory; using Ryujinx.Graphics.Memory;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenTK.Graphics.OpenGL;
namespace Ryujinx.Graphics.Texture namespace Ryujinx.Graphics.Texture
{ {
@ -336,6 +337,7 @@ namespace Ryujinx.Graphics.Texture
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);
// TODO: multi format
return Desc.BytesPerPixel * Width * Height; return Desc.BytesPerPixel * Width * Height;
} }
@ -443,5 +445,29 @@ namespace Ryujinx.Graphics.Texture
default: throw new NotImplementedException(((int)Type).ToString()); default: throw new NotImplementedException(((int)Type).ToString());
} }
} }
public static TextureTarget GetTextureTarget(TextureType TextureType)
{
switch (TextureType)
{
case TextureType.OneD:
return TextureTarget.Texture1D;
case TextureType.TwoD:
case TextureType.TwoDNoMipMap:
return TextureTarget.Texture2D;
case TextureType.ThreeD:
return TextureTarget.Texture3D;
case TextureType.OneDArray:
return TextureTarget.Texture1DArray;
case TextureType.TwoDArray:
return TextureTarget.Texture2DArray;
case TextureType.CubeMap:
return TextureTarget.TextureCubeMap;
case TextureType.CubeArray:
return TextureTarget.TextureCubeMapArray;
default:
throw new NotSupportedException($"Texture type {TextureType} currently not supported!");
}
}
} }
} }

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 System; using System;
@ -12,6 +13,8 @@ namespace Ryujinx.Graphics.Texture
GalImageFormat Format = GetImageFormat(Tic); GalImageFormat Format = GetImageFormat(Tic);
TextureType TextureType = (TextureType)((Tic[4] >> 23) & 0xF);
GalTextureSource XSource = (GalTextureSource)((Tic[0] >> 19) & 7); GalTextureSource XSource = (GalTextureSource)((Tic[0] >> 19) & 7);
GalTextureSource YSource = (GalTextureSource)((Tic[0] >> 22) & 7); GalTextureSource YSource = (GalTextureSource)((Tic[0] >> 22) & 7);
GalTextureSource ZSource = (GalTextureSource)((Tic[0] >> 25) & 7); GalTextureSource ZSource = (GalTextureSource)((Tic[0] >> 25) & 7);
@ -39,14 +42,22 @@ namespace Ryujinx.Graphics.Texture
int Width = (Tic[4] & 0xffff) + 1; int Width = (Tic[4] & 0xffff) + 1;
int Height = (Tic[5] & 0xffff) + 1; int Height = (Tic[5] & 0xffff) + 1;
int Depth = ((Tic[5] >> 16) & 0x3fff) + 1;
if (TextureType == TextureType.TwoD || TextureType == TextureType.OneD)
{
Depth = 1;
}
GalImage Image = new GalImage( GalImage Image = new GalImage(
Width, Width,
Height, Height,
Depth,
TileWidth, TileWidth,
BlockHeight, BlockHeight,
Layout, Layout,
Format, Format,
TextureType,
XSource, XSource,
YSource, YSource,
ZSource, ZSource,

View file

@ -0,0 +1,15 @@
namespace Ryujinx.Graphics.Texture
{
public enum TextureType
{
OneD = 0,
TwoD = 1,
ThreeD = 2,
CubeMap = 3,
OneDArray = 4,
TwoDArray = 5,
OneDBuffer = 6,
TwoDNoMipMap = 7,
CubeArray = 8,
}
}

View file

@ -216,10 +216,11 @@ namespace Ryujinx.Graphics.VDec
GalImage Image = new GalImage( GalImage Image = new GalImage(
OutputConfig.SurfaceWidth, OutputConfig.SurfaceWidth,
OutputConfig.SurfaceHeight, 1, OutputConfig.SurfaceHeight, 1, 1,
OutputConfig.GobBlockHeight, OutputConfig.GobBlockHeight,
GalMemoryLayout.BlockLinear, GalMemoryLayout.BlockLinear,
GalImageFormat.RGBA8 | GalImageFormat.Unorm); GalImageFormat.RGBA8 | GalImageFormat.Unorm,
TextureType.TwoD);
ImageUtils.WriteTexture(Vmm, Image, Vmm.GetPhysicalAddress(OutputConfig.SurfaceLumaAddress), Frame.Data); ImageUtils.WriteTexture(Vmm, Image, Vmm.GetPhysicalAddress(OutputConfig.SurfaceLumaAddress), Frame.Data);
} }

View file

@ -1,6 +1,8 @@
using Ryujinx.Common.Logging; 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.HLE.HOS.Kernel;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.HLE.HOS.Services.Nv.NvGpuAS; using Ryujinx.HLE.HOS.Services.Nv.NvGpuAS;
using Ryujinx.HLE.HOS.Services.Nv.NvMap; using Ryujinx.HLE.HOS.Services.Nv.NvMap;
@ -415,9 +417,10 @@ namespace Ryujinx.HLE.HOS.Services.Android
{ {
image = new GalImage( image = new GalImage(
fbWidth, fbWidth,
fbHeight, 1, BlockHeight, fbHeight, 1, 1, BlockHeight,
GalMemoryLayout.BlockLinear, GalMemoryLayout.BlockLinear,
imageFormat); imageFormat,
TextureType.TwoD);
} }
context.Device.Gpu.ResourceManager.ClearPbCache(); context.Device.Gpu.ResourceManager.ClearPbCache();