Misc. fixes on texture instructions

This commit is contained in:
gdkchan 2019-04-14 13:56:23 -03:00
parent 9db5b4a63c
commit ed97109f98
8 changed files with 111 additions and 58 deletions

View file

@ -34,8 +34,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
bool isMultisample = (texOp.Type & TextureType.Multisample) != 0;
bool isShadow = (texOp.Type & TextureType.Shadow) != 0;
string samplerName = OperandManager.GetSamplerName(context.Config.Type, texOp);
string texCall = intCoords ? "texelFetch" : "texture";
if (isGather)
@ -56,6 +54,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
texCall += "Offsets";
}
string samplerName = OperandManager.GetSamplerName(context.Config.Type, texOp);
texCall += "(" + samplerName;
int coordsCount = texOp.Type.GetCoordsCount();
@ -69,6 +69,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
arrayIndexElem = pCount++;
}
//The sampler 1D shadow overload expects a
//dummy value on the middle of the vector, who knows why...
bool hasDummy1DShadowElem = texOp.Type == (TextureType.Texture1D | TextureType.Shadow);
if (hasDummy1DShadowElem)
{
pCount++;
}
if (isShadow && !isGather)
{
pCount++;
@ -97,42 +106,46 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
texCall += ", " + str;
}
string AssembleVector(int count, VariableType type)
VariableType coordType = intCoords ? VariableType.S32 : VariableType.F32;
string AssemblePVector(int count)
{
if (count > 1)
{
string[] vecElems = new string[count];
string[] elems = new string[count];
for (int index = 0; index < count; index++)
{
if (arrayIndexElem == index)
{
arrayIndexElem = -1;
elems[index] = Src(VariableType.S32);
vecElems[index] = Src(VariableType.S32);
if (type == VariableType.F32)
if (!intCoords)
{
vecElems[index] = "float(" + vecElems[index] + ")";
elems[index] = "float(" + elems[index] + ")";
}
}
else if (index == 1 && hasDummy1DShadowElem)
{
elems[index] = NumberFormatter.FormatFloat(0);
}
else
{
vecElems[index] = Src(type);
elems[index] = Src(coordType);
}
}
string prefix = type == VariableType.F32 ? string.Empty : "i";
string prefix = intCoords ? "i" : string.Empty;
return prefix + "vec" + count + "(" + string.Join(", ", vecElems) + ")";
return prefix + "vec" + count + "(" + string.Join(", ", elems) + ")";
}
else
{
return Src(type);
return Src(coordType);
}
}
Append(AssembleVector(pCount, intCoords ? VariableType.S32 : VariableType.F32));
Append(AssemblePVector(pCount));
if (hasExtraCompareArg)
{
@ -143,33 +156,42 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{
Append(Src(VariableType.S32));
}
if (hasLodLevel)
else if (hasLodLevel)
{
Append(Src(intCoords ? VariableType.S32 : VariableType.F32));
Append(Src(coordType));
}
string AssembleOffsetVector(int count)
{
if (count > 1)
{
string[] elems = new string[count];
for (int index = 0; index < count; index++)
{
elems[index] = Src(VariableType.S32);
}
return "ivec" + count + "(" + string.Join(", ", elems) + ")";
}
else
{
return Src(VariableType.S32);
}
}
if (hasOffset)
{
Append(AssembleVector(coordsCount, VariableType.S32));
Append(AssembleOffsetVector(coordsCount));
}
else if (hasOffsets)
{
const int gatherTexelsCount = 4;
texCall += $", ivec{coordsCount}[4](";
texCall += $", ivec{coordsCount}[{gatherTexelsCount}](";
for (int index = 0; index < gatherTexelsCount; index++)
{
texCall += AssembleVector(coordsCount, VariableType.S32);
if (index < gatherTexelsCount - 1)
{
texCall += ", ";
}
}
texCall += ")";
texCall += AssembleOffsetVector(coordsCount) + ", ";
texCall += AssembleOffsetVector(coordsCount) + ", ";
texCall += AssembleOffsetVector(coordsCount) + ", ";
texCall += AssembleOffsetVector(coordsCount) + ")";
}
if (hasLodBias)

View file

@ -34,6 +34,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return true;
}
public static string FormatFloat(float value)
{
if (!TryFormatFloat(value, out string formatted))
{
throw new ArgumentException("Failed to convert float value to string.");
}
return formatted;
}
public static bool TryFormatFloat(float value, out string formatted)
{
if (float.IsNaN(value) || float.IsInfinity(value))

View file

@ -139,8 +139,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
Set("1101x00xxxxxxx", InstEmit.Texs, typeof(OpCodeTexs));
Set("1101x01xxxxxxx", InstEmit.Texs, typeof(OpCodeTlds));
Set("1101x11100xxxx", InstEmit.Texs, typeof(OpCodeTld4s));
Set("1101110000111x", InstEmit.Tld, typeof(OpCodeTld));
Set("1101110100111x", InstEmit.Tld_B, typeof(OpCodeTld));
Set("11011100xx111x", InstEmit.Tld, typeof(OpCodeTld));
Set("11011101xx111x", InstEmit.Tld_B, typeof(OpCodeTld));
Set("110010xxxx111x", InstEmit.Tld4, typeof(OpCodeTld4));
Set("1101111101001x", InstEmit.Txq, typeof(OpCodeTex));
Set("1101111101010x", InstEmit.Txq_B, typeof(OpCodeTex));

View file

@ -4,11 +4,11 @@ namespace Ryujinx.Graphics.Shader.Decoders
{
class OpCodeTex : OpCodeTexture
{
public bool HasDepthCompare { get; }
public OpCodeTex(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode)
{
HasDepthCompare = opCode.Extract(50);
HasOffset = opCode.Extract(54);
}
}
}

View file

@ -16,10 +16,12 @@ namespace Ryujinx.Graphics.Shader.Decoders
public int Immediate { get; }
public bool HasOffset { get; }
public TextureLodMode LodMode { get; protected set; }
public bool HasOffset { get; protected set; }
public bool HasDepthCompare { get; protected set; }
public bool IsMultisample { get; protected set; }
public OpCodeTexture(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode)
{
Rd = new Register(opCode.Extract(0, 8), RegisterType.Gpr);
@ -34,8 +36,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
Immediate = opCode.Extract(36, 13);
HasOffset = opCode.Extract(54);
LodMode = (TextureLodMode)opCode.Extract(55, 3);
}
}

View file

@ -4,13 +4,17 @@ namespace Ryujinx.Graphics.Shader.Decoders
{
class OpCodeTld : OpCodeTexture
{
public bool IsMultisample { get; }
public OpCodeTld(InstEmitter emitter, ulong address, long opCode) : base(emitter, address, opCode)
{
HasOffset = opCode.Extract(35);
IsMultisample = opCode.Extract(50);
LodMode = (TextureLodMode)(opCode.Extract(55, 1) + TextureLodMode.LodZero);
bool isLL = opCode.Extract(55);
LodMode = isLL
? TextureLodMode.LodLevel
: TextureLodMode.LodZero;
}
}
}

View file

@ -4,8 +4,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
{
class OpCodeTld4 : OpCodeTexture
{
public bool HasDepthCompare { get; }
public TextureGatherOffset Offset { get; }
public int GatherCompIndex { get; }

View file

@ -64,6 +64,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
return context.Copy(Register(rbIndex++, RegisterType.Gpr));
}
void AddTextureOffset(int coordsCount, int stride, int size)
{
Operand packedOffs = Rb();
for (int index = 0; index < coordsCount; index++)
{
sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * stride), Const(size)));
}
}
TextureType type;
TextureFlags flags;
@ -161,10 +171,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
break;
case TexelLoadScalarType.Texture2DLodZeroOffset:
case TexelLoadScalarType.Texture2DLodZeroMultisample:
sourcesList.Add(Ra());
sourcesList.Add(Ra());
sourcesList.Add(Const(0));
break;
case TexelLoadScalarType.Texture2DLodZeroMultisample:
sourcesList.Add(Ra());
sourcesList.Add(Ra());
sourcesList.Add(Rb());
break;
@ -192,9 +206,13 @@ namespace Ryujinx.Graphics.Shader.Instructions
sourcesList.Add(Ra());
sourcesList.Add(Ra());
sourcesList.Add(Rb());
sourcesList.Add(Rb());
break;
}
if ((flags & TextureFlags.Offset) != 0)
{
AddTextureOffset(type.GetCoordsCount(), 4, 4);
}
}
else if (op is OpCodeTld4s tld4sOp)
{
@ -221,12 +239,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (tld4sOp.HasOffset)
{
Operand packedOffs = Rb();
for (int index = 0; index < type.GetCoordsCount(); index++)
{
sourcesList.Add(context.BitfieldExtractS32(packedOffs, Const(index * 8), Const(6)));
}
AddTextureOffset(type.GetCoordsCount(), 8, 6);
flags |= TextureFlags.Offset;
}
@ -361,6 +374,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op.HasDepthCompare)
{
sourcesList.Add(Rb());
type |= TextureType.Shadow;
}
if (op.Offset != TextureGatherOffset.None)
@ -568,14 +583,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
Operand packedOffs = op.HasOffset ? Rb() : null;
if (op is OpCodeTex texOp && texOp.HasDepthCompare)
if (op.HasDepthCompare)
{
sourcesList.Add(Rb());
type |= TextureType.Shadow;
}
if (op.LodMode == TextureLodMode.LodZero ||
op.LodMode == TextureLodMode.LodLevel ||
op.LodMode == TextureLodMode.LodLevelA)
if ((op.LodMode == TextureLodMode.LodZero ||
op.LodMode == TextureLodMode.LodLevel ||
op.LodMode == TextureLodMode.LodLevelA) && !op.IsMultisample)
{
sourcesList.Add(lodValue);
@ -600,9 +617,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
flags |= TextureFlags.LodBias;
}
if (op is OpCodeTld tldOp && tldOp.IsMultisample)
if (op.IsMultisample)
{
sourcesList.Add(Rb());
type |= TextureType.Multisample;
}
Operand[] sources = sourcesList.ToArray();