Implement depth compare

This commit is contained in:
Thog 2018-11-23 12:17:52 +01:00
commit 47f6f5776f
No known key found for this signature in database
GPG key ID: 0CD291558FAFDBC6
9 changed files with 152 additions and 35 deletions

View file

@ -0,0 +1,14 @@
namespace Ryujinx.Graphics
{
public enum DepthCompareFunc
{
Never = 0,
Less = 1,
Equal = 2,
LEqual = 3,
Greater = 4,
NotEqual = 5,
GEqual = 6,
Always = 7
}
}

View file

@ -12,6 +12,9 @@ namespace Ryujinx.Graphics.Gal
public GalColorF BorderColor { get; private set; } public GalColorF BorderColor { get; private set; }
public bool DepthCompare { get; private set; }
public DepthCompareFunc DepthCompareFunc { get; private set; }
public GalTextureSampler( public GalTextureSampler(
GalTextureWrap AddressU, GalTextureWrap AddressU,
GalTextureWrap AddressV, GalTextureWrap AddressV,
@ -19,7 +22,9 @@ namespace Ryujinx.Graphics.Gal
GalTextureFilter MinFilter, GalTextureFilter MinFilter,
GalTextureFilter MagFilter, GalTextureFilter MagFilter,
GalTextureMipFilter MipFilter, GalTextureMipFilter MipFilter,
GalColorF BorderColor) GalColorF BorderColor,
bool DepthCompare,
DepthCompareFunc DepthCompareFunc)
{ {
this.AddressU = AddressU; this.AddressU = AddressU;
this.AddressV = AddressV; this.AddressV = AddressV;
@ -28,6 +33,9 @@ namespace Ryujinx.Graphics.Gal
this.MagFilter = MagFilter; this.MagFilter = MagFilter;
this.MipFilter = MipFilter; this.MipFilter = MipFilter;
this.BorderColor = BorderColor; this.BorderColor = BorderColor;
this.DepthCompare = DepthCompare;
this.DepthCompareFunc = DepthCompareFunc;
} }
} }
} }

View file

@ -189,6 +189,31 @@ namespace Ryujinx.Graphics.Gal.OpenGL
throw new NotImplementedException($"{Format & GalImageFormat.FormatMask} {Format & GalImageFormat.TypeMask}"); throw new NotImplementedException($"{Format & GalImageFormat.FormatMask} {Format & GalImageFormat.TypeMask}");
} }
public static All GetDepthCompareFunc(DepthCompareFunc DepthCompareFunc)
{
switch (DepthCompareFunc)
{
case DepthCompareFunc.LEqual:
return All.Lequal;
case DepthCompareFunc.GEqual:
return All.Gequal;
case DepthCompareFunc.Less:
return All.Less;
case DepthCompareFunc.Greater:
return All.Greater;
case DepthCompareFunc.Equal:
return All.Equal;
case DepthCompareFunc.NotEqual:
return All.Notequal;
case DepthCompareFunc.Always:
return All.Always;
case DepthCompareFunc.Never:
return All.Never;
default:
throw new ArgumentException(nameof(DepthCompareFunc) + " \"" + DepthCompareFunc + "\" is not valid!");
}
}
public static InternalFormat GetCompressedImageFormat(GalImageFormat Format) public static InternalFormat GetCompressedImageFormat(GalImageFormat Format)
{ {
switch (Format) switch (Format)

View file

@ -370,6 +370,17 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}; };
GL.TexParameter(Target, TextureParameterName.TextureBorderColor, Color); GL.TexParameter(Target, TextureParameterName.TextureBorderColor, Color);
if (Sampler.DepthCompare)
{
GL.TexParameter(Target, TextureParameterName.TextureCompareMode, (int)All.CompareRToTexture);
GL.TexParameter(Target, TextureParameterName.TextureCompareFunc, (int)OGLEnumConverter.GetDepthCompareFunc(Sampler.DepthCompareFunc));
}
else
{
GL.TexParameter(Target, TextureParameterName.TextureCompareMode, (int)All.None);
GL.TexParameter(Target, TextureParameterName.TextureCompareFunc, (int)All.Never);
}
} }
} }
} }

View file

@ -236,17 +236,23 @@ namespace Ryujinx.Graphics.Gal.Shader
TextureType TextureType; TextureType TextureType;
TextureInstructionSuffix TextureInstructionSuffix;
// TODO: non 2d texture type for TEXQ? // TODO: non 2d texture type for TEXQ?
if (Op.Inst == ShaderIrInst.Texq) if (Op.Inst == ShaderIrInst.Texq)
{ {
TextureType = TextureType.TwoD; TextureType = TextureType.TwoD;
TextureInstructionSuffix = TextureInstructionSuffix.None;
} }
else else
{ {
TextureType = ((ShaderIrMetaTex)Op.MetaData).TextureType; ShaderIrMetaTex Meta = ((ShaderIrMetaTex)Op.MetaData);
TextureType = Meta.TextureType;
TextureInstructionSuffix = Meta.TextureInstructionSuffix;
} }
m_Textures.TryAdd(Handle, new ShaderDeclInfo(Name, Handle, false, 0, 1, TextureType)); m_Textures.TryAdd(Handle, new ShaderDeclInfo(Name, Handle, false, 0, 1, TextureType, TextureInstructionSuffix));
} }
else if (Op.Inst == ShaderIrInst.Texb) else if (Op.Inst == ShaderIrInst.Texb)
{ {
@ -271,9 +277,10 @@ namespace Ryujinx.Graphics.Gal.Shader
if (HandleSrc != null && HandleSrc is ShaderIrOperCbuf Cbuf) if (HandleSrc != null && HandleSrc is ShaderIrOperCbuf Cbuf)
{ {
ShaderIrMetaTex Meta = ((ShaderIrMetaTex)Op.MetaData);
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, 1, ((ShaderIrMetaTex)Op.MetaData).TextureType)); m_CbTextures.Add(Op, new ShaderDeclInfo(Name, Cbuf.Pos, true, Cbuf.Index, 1, Meta.TextureType, Meta.TextureInstructionSuffix));
} }
else else
{ {

View file

@ -221,35 +221,54 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
private string GetSamplerType(TextureTarget TextureTarget) private string GetSamplerType(TextureTarget TextureTarget, bool HasShadow)
{ {
string Result;
switch (TextureTarget) switch (TextureTarget)
{ {
case TextureTarget.Texture1D: case TextureTarget.Texture1D:
return "sampler1D"; Result = "sampler1D";
break;
case TextureTarget.Texture2D: case TextureTarget.Texture2D:
return "sampler2D"; Result = "sampler2D";
break;
case TextureTarget.Texture3D: case TextureTarget.Texture3D:
return "sampler3D"; Result = "sampler3D";
break;
case TextureTarget.TextureCubeMap: case TextureTarget.TextureCubeMap:
return "samplerCube"; Result = "samplerCube";
break;
case TextureTarget.TextureRectangle: case TextureTarget.TextureRectangle:
return "sampler2DRect"; Result = "sampler2DRect";
break;
case TextureTarget.Texture1DArray: case TextureTarget.Texture1DArray:
return "sampler1DArray"; Result = "sampler1DArray";
break;
case TextureTarget.Texture2DArray: case TextureTarget.Texture2DArray:
return "sampler2DArray"; Result = "sampler2DArray";
break;
case TextureTarget.TextureCubeMapArray: case TextureTarget.TextureCubeMapArray:
return "samplerCubeArray"; Result = "samplerCubeArray";
break;
case TextureTarget.TextureBuffer: case TextureTarget.TextureBuffer:
return "samplerBuffer"; Result = "samplerBuffer";
break;
case TextureTarget.Texture2DMultisample: case TextureTarget.Texture2DMultisample:
return "sampler2DMS"; Result = "sampler2DMS";
break;
case TextureTarget.Texture2DMultisampleArray: case TextureTarget.Texture2DMultisampleArray:
return "sampler2DMSArray"; Result = "sampler2DMSArray";
break;
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
} }
if (HasShadow)
Result += "Shadow";
return Result;
} }
private void PrintDeclTextures() private void PrintDeclTextures()
@ -257,15 +276,15 @@ namespace Ryujinx.Graphics.Gal.Shader
foreach (ShaderDeclInfo DeclInfo in IterateCbTextures()) foreach (ShaderDeclInfo DeclInfo in IterateCbTextures())
{ {
TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType); TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType);
SB.AppendLine($"// {DeclInfo.TextureSuffix}");
SB.AppendLine("uniform " + GetSamplerType(Target) + " " + DeclInfo.Name + ";"); SB.AppendLine("uniform " + GetSamplerType(Target, (DeclInfo.TextureSuffix & TextureInstructionSuffix.DC) != 0) + " " + DeclInfo.Name + ";");
} }
foreach (ShaderDeclInfo DeclInfo in Decl.Textures.Values.OrderBy(DeclKeySelector)) foreach (ShaderDeclInfo DeclInfo in Decl.Textures.Values.OrderBy(DeclKeySelector))
{ {
TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType); TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType);
SB.AppendLine($"// {DeclInfo.TextureSuffix}");
SB.AppendLine("uniform " + GetSamplerType(Target) + " " + DeclInfo.Name + ";"); SB.AppendLine("uniform " + GetSamplerType(Target, (DeclInfo.TextureSuffix & TextureInstructionSuffix.DC) != 0) + " " + DeclInfo.Name + ";");
} }
} }
@ -1303,10 +1322,13 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData; ShaderIrMetaTex Meta = (ShaderIrMetaTex)Op.MetaData;
bool HasDepth = (Meta.TextureInstructionSuffix & TextureInstructionSuffix.DC) != 0;
int Coords = ImageUtils.GetCoordsCountTextureType(Meta.TextureType); int Coords = ImageUtils.GetCoordsCountTextureType(Meta.TextureType);
bool IsArray = ImageUtils.IsArray(Meta.TextureType); bool IsArray = ImageUtils.IsArray(Meta.TextureType);
string GetLastArgument(ShaderIrNode Node) string GetLastArgument(ShaderIrNode Node)
{ {
string Result = GetOperExpr(Op, Node); string Result = GetOperExpr(Op, Node);
@ -1321,23 +1343,35 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
string LastArgument; string LastArgument;
string DepthArgument = "";
int VecSize = Coords;
if (HasDepth)
{
VecSize++;
DepthArgument = $", {GetOperExpr(Op, Meta.DepthCompare)}";
}
switch (Coords) switch (Coords)
{ {
case 1: case 1:
if (HasDepth)
{
return $"vec2({GetOperExpr(Op, Meta.Coordinates[0])}{DepthArgument})";
}
return GetOperExpr(Op, Meta.Coordinates[0]); return GetOperExpr(Op, Meta.Coordinates[0]);
case 2: case 2:
LastArgument = GetLastArgument(Meta.Coordinates[1]); LastArgument = GetLastArgument(Meta.Coordinates[1]);
return "vec2(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + LastArgument + ")"; return $"vec{VecSize}({GetOperExpr(Op, Meta.Coordinates[0])}, {LastArgument}{DepthArgument})";
case 3: case 3:
LastArgument = GetLastArgument(Meta.Coordinates[2]); LastArgument = GetLastArgument(Meta.Coordinates[2]);
return "vec3(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + GetOperExpr(Op, Meta.Coordinates[1]) + ", " + LastArgument + ")"; return $"vec{VecSize}({GetOperExpr(Op, Meta.Coordinates[0])}, {GetOperExpr(Op, Meta.Coordinates[1])}, {LastArgument}{DepthArgument})";
case 4: case 4:
LastArgument = GetLastArgument(Meta.Coordinates[3]); LastArgument = GetLastArgument(Meta.Coordinates[3]);
return "vec4(" + GetOperExpr(Op, Meta.Coordinates[0]) + ", " + GetOperExpr(Op, Meta.Coordinates[1]) + ", " + GetOperExpr(Op, Meta.Coordinates[2]) + ", " + LastArgument + ")"; return $"vec4({GetOperExpr(Op, Meta.Coordinates[0])}, {GetOperExpr(Op, Meta.Coordinates[1])}, {GetOperExpr(Op, Meta.Coordinates[2])}, {LastArgument}){DepthArgument}";
default: default:
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
@ -1378,6 +1412,13 @@ namespace Ryujinx.Graphics.Gal.Shader
TextureInstructionSuffix Suffix = Meta.TextureInstructionSuffix; TextureInstructionSuffix Suffix = Meta.TextureInstructionSuffix;
string ChString = "." + Ch;
if ((Suffix & TextureInstructionSuffix.DC) != 0)
{
ChString = "";
}
// TODO: support LBA and LLA and DC // TODO: support LBA and LLA and DC
if ((Suffix & TextureInstructionSuffix.LZ) != 0) if ((Suffix & TextureInstructionSuffix.LZ) != 0)
{ {
@ -1385,10 +1426,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
string Offset = GetTextureOffset(Meta, "floatBitsToInt((" + GetOperExpr(Op, Meta.Offset) + "))"); string Offset = GetTextureOffset(Meta, "floatBitsToInt((" + GetOperExpr(Op, Meta.Offset) + "))");
return "textureLodOffset(" + Sampler + ", " + Coords + ", 0.0, " + Offset + ")." + Ch; return "textureLodOffset(" + Sampler + ", " + Coords + ", 0.0, " + Offset + ")" + ChString;
} }
return "textureLod(" + Sampler + ", " + Coords + ", 0.0)." + Ch; return "textureLod(" + Sampler + ", " + Coords + ", 0.0)" + ChString;
} }
else if ((Suffix & TextureInstructionSuffix.LB) != 0) else if ((Suffix & TextureInstructionSuffix.LB) != 0)
{ {
@ -1396,10 +1437,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
string Offset = GetTextureOffset(Meta, "floatBitsToInt((" + GetOperExpr(Op, Meta.Offset) + "))"); string Offset = GetTextureOffset(Meta, "floatBitsToInt((" + GetOperExpr(Op, Meta.Offset) + "))");
return "textureOffset(" + Sampler + ", " + Coords + ", " + Offset + ", " + GetOperExpr(Op, Meta.LevelOfDetail) + ")." + Ch; return "textureOffset(" + Sampler + ", " + Coords + ", " + Offset + ", " + GetOperExpr(Op, Meta.LevelOfDetail) + ")" + ChString;
} }
return "texture(" + Sampler + ", " + Coords + ", " + GetOperExpr(Op, Meta.LevelOfDetail) + ")." + Ch; return "texture(" + Sampler + ", " + Coords + ", " + GetOperExpr(Op, Meta.LevelOfDetail) + ")" + ChString;
} }
else if ((Suffix & TextureInstructionSuffix.LL) != 0) else if ((Suffix & TextureInstructionSuffix.LL) != 0)
{ {
@ -1407,22 +1448,22 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
string Offset = GetTextureOffset(Meta, "floatBitsToInt((" + GetOperExpr(Op, Meta.Offset) + "))"); string Offset = GetTextureOffset(Meta, "floatBitsToInt((" + GetOperExpr(Op, Meta.Offset) + "))");
return "textureLodOffset(" + Sampler + ", " + Coords + ", " + GetOperExpr(Op, Meta.LevelOfDetail) + ", " + Offset + ")." + Ch; return "textureLodOffset(" + Sampler + ", " + Coords + ", " + GetOperExpr(Op, Meta.LevelOfDetail) + ", " + Offset + ")" + ChString;
} }
return "textureLod(" + Sampler + ", " + Coords + ", " + GetOperExpr(Op, Meta.LevelOfDetail) + ")." + Ch; return "textureLod(" + Sampler + ", " + Coords + ", " + GetOperExpr(Op, Meta.LevelOfDetail) + ")" + ChString;
} }
else if (Suffix == TextureInstructionSuffix.AOFFI) else if (Suffix == TextureInstructionSuffix.AOFFI)
{ {
string Offset = GetTextureOffset(Meta, "floatBitsToInt((" + GetOperExpr(Op, Meta.Offset) + "))"); string Offset = GetTextureOffset(Meta, "floatBitsToInt((" + GetOperExpr(Op, Meta.Offset) + "))");
return "textureOffset(" + Sampler + ", " + Coords + ", " + Offset + ")." + Ch; return "textureOffset(" + Sampler + ", " + Coords + ", " + Offset + ")" + ChString;
} }
else if (Suffix == TextureInstructionSuffix.None || Suffix == TextureInstructionSuffix.DC) else
{ {
// FIXME: implement DC // FIXME: implement DC
// Load Standard // Load Standard
return "texture(" + Sampler + ", " + Coords + ")." + Ch; return "texture(" + Sampler + ", " + Coords + ")" + ChString;
} }
throw new NotImplementedException($"Texture Suffix {Meta.TextureInstructionSuffix} is not implemented"); throw new NotImplementedException($"Texture Suffix {Meta.TextureInstructionSuffix} is not implemented");

View file

@ -13,13 +13,16 @@ namespace Ryujinx.Graphics.Gal
public TextureType TextureType { get; private set; } public TextureType TextureType { get; private set; }
public TextureInstructionSuffix TextureSuffix { 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) TextureType TextureType = TextureType.TwoD,
TextureInstructionSuffix TextureSuffix = TextureInstructionSuffix.None)
{ {
this.Name = Name; this.Name = Name;
this.Index = Index; this.Index = Index;
@ -27,6 +30,8 @@ namespace Ryujinx.Graphics.Gal
this.Cbuf = Cbuf; this.Cbuf = Cbuf;
this.Size = Size; this.Size = Size;
this.TextureType = TextureType; this.TextureType = TextureType;
this.TextureSuffix = TextureSuffix;
} }
internal void Enlarge(int NewSize) internal void Enlarge(int NewSize)

View file

@ -94,6 +94,10 @@ namespace Ryujinx.Graphics.Texture
GalTextureWrap AddressV = (GalTextureWrap)((Tsc[0] >> 3) & 7); GalTextureWrap AddressV = (GalTextureWrap)((Tsc[0] >> 3) & 7);
GalTextureWrap AddressP = (GalTextureWrap)((Tsc[0] >> 6) & 7); GalTextureWrap AddressP = (GalTextureWrap)((Tsc[0] >> 6) & 7);
bool DepthCompare = ((Tsc[0] >> 9) & 1) == 1;
DepthCompareFunc DepthCompareFunc = (DepthCompareFunc)((Tsc[0] >> 10) & 7);
GalTextureFilter MagFilter = (GalTextureFilter) ((Tsc[1] >> 0) & 3); GalTextureFilter MagFilter = (GalTextureFilter) ((Tsc[1] >> 0) & 3);
GalTextureFilter MinFilter = (GalTextureFilter) ((Tsc[1] >> 4) & 3); GalTextureFilter MinFilter = (GalTextureFilter) ((Tsc[1] >> 4) & 3);
GalTextureMipFilter MipFilter = (GalTextureMipFilter)((Tsc[1] >> 6) & 3); GalTextureMipFilter MipFilter = (GalTextureMipFilter)((Tsc[1] >> 6) & 3);
@ -111,7 +115,9 @@ namespace Ryujinx.Graphics.Texture
MinFilter, MinFilter,
MagFilter, MagFilter,
MipFilter, MipFilter,
BorderColor); BorderColor,
DepthCompare,
DepthCompareFunc);
} }
private static GalImageFormat GetImageFormat(int[] Tic) private static GalImageFormat GetImageFormat(int[] Tic)

View file

@ -3,7 +3,7 @@
namespace Ryujinx.Graphics.Texture namespace Ryujinx.Graphics.Texture
{ {
[Flags] [Flags]
enum TextureInstructionSuffix public enum TextureInstructionSuffix
{ {
None = 0x00, // No Modifier None = 0x00, // No Modifier
LZ = 0x02, // Load LOD Zero LZ = 0x02, // Load LOD Zero