Implement depth compare

This commit is contained in:
Thog 2018-11-23 12:17:52 +01:00
parent df99afeded
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 bool DepthCompare { get; private set; }
public DepthCompareFunc DepthCompareFunc { get; private set; }
public GalTextureSampler(
GalTextureWrap AddressU,
GalTextureWrap AddressV,
@ -19,7 +22,9 @@ namespace Ryujinx.Graphics.Gal
GalTextureFilter MinFilter,
GalTextureFilter MagFilter,
GalTextureMipFilter MipFilter,
GalColorF BorderColor)
GalColorF BorderColor,
bool DepthCompare,
DepthCompareFunc DepthCompareFunc)
{
this.AddressU = AddressU;
this.AddressV = AddressV;
@ -28,6 +33,9 @@ namespace Ryujinx.Graphics.Gal
this.MagFilter = MagFilter;
this.MipFilter = MipFilter;
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}");
}
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)
{
switch (Format)

View file

@ -370,6 +370,17 @@ namespace Ryujinx.Graphics.Gal.OpenGL
};
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

@ -235,18 +235,24 @@ namespace Ryujinx.Graphics.Gal.Shader
string Name = StagePrefix + TextureName + Index;
TextureType TextureType;
TextureInstructionSuffix TextureInstructionSuffix;
// TODO: non 2d texture type for TEXQ?
if (Op.Inst == ShaderIrInst.Texq)
{
TextureType = TextureType.TwoD;
TextureInstructionSuffix = TextureInstructionSuffix.None;
}
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)
{
@ -271,9 +277,10 @@ namespace Ryujinx.Graphics.Gal.Shader
if (HandleSrc != null && HandleSrc is ShaderIrOperCbuf Cbuf)
{
ShaderIrMetaTex Meta = ((ShaderIrMetaTex)Op.MetaData);
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
{

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)
{
case TextureTarget.Texture1D:
return "sampler1D";
Result = "sampler1D";
break;
case TextureTarget.Texture2D:
return "sampler2D";
Result = "sampler2D";
break;
case TextureTarget.Texture3D:
return "sampler3D";
Result = "sampler3D";
break;
case TextureTarget.TextureCubeMap:
return "samplerCube";
Result = "samplerCube";
break;
case TextureTarget.TextureRectangle:
return "sampler2DRect";
Result = "sampler2DRect";
break;
case TextureTarget.Texture1DArray:
return "sampler1DArray";
Result = "sampler1DArray";
break;
case TextureTarget.Texture2DArray:
return "sampler2DArray";
Result = "sampler2DArray";
break;
case TextureTarget.TextureCubeMapArray:
return "samplerCubeArray";
Result = "samplerCubeArray";
break;
case TextureTarget.TextureBuffer:
return "samplerBuffer";
Result = "samplerBuffer";
break;
case TextureTarget.Texture2DMultisample:
return "sampler2DMS";
Result = "sampler2DMS";
break;
case TextureTarget.Texture2DMultisampleArray:
return "sampler2DMSArray";
Result = "sampler2DMSArray";
break;
default:
throw new NotSupportedException();
}
if (HasShadow)
Result += "Shadow";
return Result;
}
private void PrintDeclTextures()
@ -257,15 +276,15 @@ namespace Ryujinx.Graphics.Gal.Shader
foreach (ShaderDeclInfo DeclInfo in IterateCbTextures())
{
TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType);
SB.AppendLine("uniform " + GetSamplerType(Target) + " " + DeclInfo.Name + ";");
SB.AppendLine($"// {DeclInfo.TextureSuffix}");
SB.AppendLine("uniform " + GetSamplerType(Target, (DeclInfo.TextureSuffix & TextureInstructionSuffix.DC) != 0) + " " + DeclInfo.Name + ";");
}
foreach (ShaderDeclInfo DeclInfo in Decl.Textures.Values.OrderBy(DeclKeySelector))
{
TextureTarget Target = ImageUtils.GetTextureTarget(DeclInfo.TextureType);
SB.AppendLine("uniform " + GetSamplerType(Target) + " " + DeclInfo.Name + ";");
SB.AppendLine($"// {DeclInfo.TextureSuffix}");
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;
bool HasDepth = (Meta.TextureInstructionSuffix & TextureInstructionSuffix.DC) != 0;
int Coords = ImageUtils.GetCoordsCountTextureType(Meta.TextureType);
bool IsArray = ImageUtils.IsArray(Meta.TextureType);
string GetLastArgument(ShaderIrNode Node)
{
string Result = GetOperExpr(Op, Node);
@ -1321,23 +1343,35 @@ namespace Ryujinx.Graphics.Gal.Shader
}
string LastArgument;
string DepthArgument = "";
int VecSize = Coords;
if (HasDepth)
{
VecSize++;
DepthArgument = $", {GetOperExpr(Op, Meta.DepthCompare)}";
}
switch (Coords)
{
case 1:
if (HasDepth)
{
return $"vec2({GetOperExpr(Op, Meta.Coordinates[0])}{DepthArgument})";
}
return GetOperExpr(Op, Meta.Coordinates[0]);
case 2:
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:
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:
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:
throw new InvalidOperationException();
}
@ -1378,6 +1412,13 @@ namespace Ryujinx.Graphics.Gal.Shader
TextureInstructionSuffix Suffix = Meta.TextureInstructionSuffix;
string ChString = "." + Ch;
if ((Suffix & TextureInstructionSuffix.DC) != 0)
{
ChString = "";
}
// TODO: support LBA and LLA and DC
if ((Suffix & TextureInstructionSuffix.LZ) != 0)
{
@ -1385,10 +1426,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{
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)
{
@ -1396,10 +1437,10 @@ namespace Ryujinx.Graphics.Gal.Shader
{
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)
{
@ -1407,22 +1448,22 @@ namespace Ryujinx.Graphics.Gal.Shader
{
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)
{
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
// Load Standard
return "texture(" + Sampler + ", " + Coords + ")." + Ch;
return "texture(" + Sampler + ", " + Coords + ")" + ChString;
}
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 TextureInstructionSuffix TextureSuffix { get; private set; }
public ShaderDeclInfo(
string Name,
int Index,
bool IsCb = false,
int Cbuf = 0,
int Size = 1,
TextureType TextureType = TextureType.TwoD)
TextureType TextureType = TextureType.TwoD,
TextureInstructionSuffix TextureSuffix = TextureInstructionSuffix.None)
{
this.Name = Name;
this.Index = Index;
@ -27,6 +30,8 @@ namespace Ryujinx.Graphics.Gal
this.Cbuf = Cbuf;
this.Size = Size;
this.TextureType = TextureType;
this.TextureSuffix = TextureSuffix;
}
internal void Enlarge(int NewSize)

View file

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

View file

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