Misc. fixes on texture instructions
This commit is contained in:
parent
9db5b4a63c
commit
ed97109f98
8 changed files with 111 additions and 58 deletions
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,8 +4,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||
{
|
||||
class OpCodeTld4 : OpCodeTexture
|
||||
{
|
||||
public bool HasDepthCompare { get; }
|
||||
|
||||
public TextureGatherOffset Offset { get; }
|
||||
|
||||
public int GatherCompIndex { get; }
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Reference in a new issue